我正在尝试按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将不同。
我目前使用的解决方法是将图书ID存储在ndb.KeyProperty
或ndb.IntegerProperty
中,但这实际上是多余的信息,因为评论的ID已经相同。
有没有办法只通过密钥ID进行查询,不包括父ID?
答案 0 :(得分:2)
您可以使用类似的内容按ID查询: review = Review.get_by_id(book.key.id())
。
只有在书籍和评论之间存在1对1关系时,您设置ID的方法才有效,因为密钥是唯一的。上述操作只返回一个实体。
我建议将最常用的查询设置为审核的祖先。我的猜测是,除非你的用户是着名的评论家,否则他所评论的评论是最相关的。
如果您将Review的父级设置为Book,则可以使用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()