2017-03-01 65 views
1

我正在爲經典的「用戶帖子」和「標籤」問題設計谷歌數據存儲架構。關係索引實體和投影查詢

page建議關係指數實體模型。基本上它將可搜索的標籤或關鍵字放置在子實體中用於過濾的列表屬性以及父實體中的必要屬性。據我瞭解,這種方法是在查詢時減少序列化開銷。

class Post(db.Model): 
    title = db.StringProperty() 
    post_date = db.DateTimeProperty() 

class Tags(db.Model): 
    tags = db.StringListProperty() 

mytags = Tags(parent=post, tags=many_tags) 
  1. 鑑於projection queries可以得到屬性的子集,是關係指數實體仍然需要減少列表屬性的序列化的開銷?

注意:投影查詢有limits;關係指數實體不。

  1. 關係指標實體是否使查詢更加困難?說我想過濾在過去7天內創建的帖子的標籤'汽車'的帖子。標籤和post_date是不同的,有沒有簡單的方法來做到這一點?

  2. 關於爆炸指數,關係指數實體是否減少了爆炸指數的機會,因爲它將列表屬性置於不同的類型?

感謝您提前回答。

+0

附註:從https://cloud.google.com/appengine/docs/standard/python/datastore/api-overview:「注意:強烈建議開發人員構建新應用程序以使用NDB客戶端庫,該庫有幾個與此客戶端庫相比的優勢,例如通過Memcache API進行自動實體緩存如果您當前正在使用舊版DB客戶端Li brary,閱讀DB到NDB移植指南「 –

回答

1
  1. 的關係指數實體溶液減少了在任何類型訪問該Post實體,包括像key.get() OPS,`entity.put()或取非投影查詢序列化的開銷,而只有投影查詢這樣做,取得各自的查詢結果。

  2. 是的,查詢有點困難。對於你的例子,你需要單獨的查詢,每個實體類型一個。

的例子假設使用ndb,不db

from google.appengine.ext import ndb 

class Post(ndb.Model): 
    title = ndb.StringProperty() 
    post_date = ndb.DateTimeProperty() 

class Tags(ndb.Model): 
    tags = ndb.StringProperty(repeated=True) 

我會使用純鍵查詢,因爲他們是更便宜,速度更快:

from datetime import datetime, timedelta 

car_post_keys = [] 
post_keys = Post.query(Post.post_date>(datetime.utcnow() - timedelta(days=7)), 
         keys_only=True).fetch() 
if post_keys is not None: 
    for post_key in post_keys: 
     if Tags.query(Tags.tags=='car', ancestor=post_key, keys_only=True).fetch() is not None: 
      car_post_keys.append(post_key) 

car_posts = ndb.get_multi(car_post_keys) if car_post_keys else [] 
  • 一般來說,答案是肯定的,正是因爲你提到的原因。在您的特定示例中,只有一個屬性具有多個值 - tags - 以及其他幾個屬性,均具有單一值,因此爆炸性索引影響的差異可能會疏忽。
  • 將實體拆分成幾個較小的實體是其他原因的常用技術,例如請參閱re-using an entity's ID for other entities of different kinds - sane idea?

    這裏是這裏運用這一理念的一個例子:

    car_post_key_ids = [] 
    
    post_keys = Post.query(Post.post_date>(datetime.utcnow() - timedelta(days=7)), 
             keys_only=True).fetch() 
    if post_keys is not None: 
        post_key_ids = [key.id() for key in post_keys] 
    
        car_tag_keys = Tags.query(Tags.tags=='car', keys_only=True).fetch() 
        car_tag_key_ids = [key.id() for key in car_tag_keys] if car_tag_keys is not None else [] 
    
        car_post_key_ids = list(set(post_key_ids) & set(car_tag_key_ids)) 
    
    car_posts = [Post.get_by_id(id) for id in car_post_key_ids] 
    

    的例子是相當簡單的,他們可以使用ndb異步調用,任務/任務蕾進行優化,可能需要許多成果光標等

    +0

    感謝您的回答。關於2中的查詢,你可以給一個例子或指針如何有效地執行兩段查詢嗎?如果可能的話使用NDB,或只是解釋邏輯。謝謝。 – YSC