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.KeyPropertyまたはndb.IntegerPropertyに保存することですが、レビューの ID が既に同じであるため、事実上冗長な情報です。

親 ID を除外して、キー ID のみでクエリを実行する方法はありますか?

4

1 に答える 1

2

ID でクエリするには、次のようなものを使用します: review = Review.get_by_id(book.key.id())

ID を設定するアプローチは、キーが一意であるため、本とレビューの間に 1 対 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 に答える