2017-03-01 63 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