1

我试图通过他们的 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.KeyPropertyorndb.IntegerProperty中,但这实际上是冗余信息,因为评论的 ID 已经相同。

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

4

1 回答 1

2

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

您设置 ID 的方法仅适用于书籍和评论之间存在 1 对 1 关系的情况,因为键是唯一的。上述操作只会返回一个实体。

我建议将最常用的查询设置为审查的祖先。我的猜测是,除非您的用户是著名的评论家,否则他的书评所属的书在这里是最相关的。

如果您将 Review 的父级设置为 Book,则可以使用Ancestor 查询来获取所有具有保证一致性的评论。然后用户可以是评论的属性,您可以简单地按该属性进行过滤。我建议使用 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()
于 2012-12-27T17:32:01.447 回答