如何按ID查询实体

时间:2012-12-27 12:41:05

标签: google-app-engine app-engine-ndb

我正在尝试按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.KeyPropertyndb.IntegerProperty中,但这实际上是多余的信息,因为评论的ID已经相同。

有没有办法只通过密钥ID进行查询,不包括父ID?

1 个答案:

答案 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()