2012-12-27 65 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個結果。 –