2012-12-27 66 views
1

我想通过它们的ID查询实体,但不包括它们的父ID。如何通过ID查询实体

下面是一些代码,以帮助解释:

class Book(ndb.Model): 
    ... 

class User(ndb.Model): 
    ... 
class Review(ndb.Model): 
    ... 

当我创建Review对象,我把他们的父母是用户,他们的ID是一样的书ID:

review = Review(key=ndb.Key('Review', book.key.id(), parent=user.key)) 

现在我想知道每本书有多少评论,通过查询。由完整的密钥查询将无法正常工作,因为父ID会有所不同。

我目前使用的是储存在ndb.KeyPropertyndb.IntegerProperty书ID,但实际上是作为审查的ID将已经是同一个冗余信息的解决方法。

有什么办法只由密钥ID做了查询,但不包括父ID?

+1

我不hting有一个正式的方式。存储参考资产是一个好主意,您可以获得如下书籍评论: book.reviews。此外,为什么你将父母设置为用户而不是书本?如果你想删除一本书,所有它的评论,你会怎么做呢? –

+0

@JimmyKane这本书回顾的例子只是我正在做的一个精简版;我需要亲子关系是这样的,因为我的应用程序在一个事务中编辑了很多“评论”,所以它需要锁定用户的实体组才能工作。 –

+0

锁定用户的实体组,例如为了确保用户没有被删除或类似的东西? –

回答

2

你会使用这样的ID来查询:review = Review.get_by_id(book.key.id())

你设置ID的方法只如果有一本书和审查之间的1对1的关系,因为钥匙是独一无二的作品。上述操作只会返回一个实体。

我建议设置最常用的查询为始祖的审查。我的猜测是,他所撰写的评论所属的版本是最相关的,除非你的用户是着名的评论家。

如果设置了审查的父的书,你可以使用Ancestor queries让所有的与保证一致性的审查。然后,用户可以成为评论的属性,您可以简单地按照该属性进行过滤。我建议使用KeyProperty作为参考。

如果你想为用户查询保证一致性,保持审查书籍列表为每个用户(重复KeyProperty),然后运行对审查,该用户过滤祖先查询。

更新: @JimmyKane是正确的 - get_by_id根本不会工作,因为它显然需要父指定,并且在你的情况下,这似乎不太实际。这证明了get_by_id将无法正常工作

代码:

from flask import Flask 

from google.appengine.ext import ndb 

app = Flask(__name__) 

class User(ndb.Model): 
    name = ndb.StringProperty() 

class Book(ndb.Model): 
    name = ndb.StringProperty() 

class Review(ndb.Model): 
    name = ndb.StringProperty() 

@app.route('/') 
def hello_main(): 
    user = User() 
    user.name = 'Test User1' 
    user.put() 

    book = Book() 
    book.name = 'Test Book1' 
    book.put() 

    review = Review(id=book.key.id(), parent=user.key) 
    review.name = 'Test Review1' 
    review.put() 

    return 'Review saved!' 

@app.route('/reviews/') 
def reviews(): 
    book = Book.query(Book.name == 'Test Book1').get() 
    user = User.query(User.name == 'Test User1').get() 

    if book: 
     review = Review.get_by_id(book.key.id(), parent=user.key) 
     if review: 
      return review.name 
     else: 
      return 'no review' 
    else: 
     return 'no books' 


if __name__ == "__main__": 
    app.run() 

而这里的示例代码为我推荐的方法:

from flask import Flask 

from google.appengine.ext import ndb 

class User(ndb.Model): 
    name = ndb.StringProperty() 
    reviews = ndb.KeyProperty(repeated=True) 

class Book(ndb.Model): 
    name = ndb.StringProperty() 

class Review(ndb.Model): 
    name = ndb.StringProperty() 

app = Flask(__name__) 

@app.route('/') 
def hello_main(): 
    user = User() 
    user.name = 'Test User1' 
    user.put() 

    book = Book() 
    book.name = 'Test Book1' 
    book.put() 

    review = Review(parent=book.key) 
    review.name = 'Test Review1' 
    review.put() 

    user.reviews.append(review.key) 
    user.put() 

    return 'Review saved!' 

@app.route('/add_review/') 
def add_review(): 
    book = Book.query(Book.name == 'Test Book1').get() 
    user = User.query(User.name == 'Test User1').get() 

    if book: 
     review = Review(parent=book.key) 
     review.name = 'Test Review' 
     review.put() 

     user.reviews.append(review.key) 
     user.put() 

     return 'review added' 
    else: 
     return 'no books' 

@app.route('/reviews/') 
def reviews(): 
    book = Book.query(Book.name == 'Test Book1').get() 
    user = User.query(User.name == 'Test User1').get() 

    if book: 
     reviews = Review.query(ancestor=book.key) 
     for review in reviews: 
      print(review.name) 
      print('<br/>') 
     return '' 
    else: 
     return 'no books' 


@app.route('/reviews_by_user/') 
def reviews_by_user(): 
    user = User.query(User.name == 'Test User1').get() 

    for review_key in user.reviews: 
     review = review_key.get() 
     print(review.name) 
     print('<br/>') 
    return '' 



if __name__ == "__main__": 
    app.run() 
+0

不检查= Review.get_by_id(book.key.id(),parent = None)? 它不会返回任何东西... –

+0

@JimmyKane,不知道你在问什么...你能请你改说一下吗? – Sologoub

+1

get_by_id方法是否需要父级?如果没有给出父母,则暗示为无。所以在你的例子中,get_by_id将返回0个结果。 –