关系索引实体和预测查询

时间:2017-03-01 05:03:23

标签: google-app-engine google-cloud-datastore

我正在为经典的“用户帖子”和“标签”问题设计谷歌数据存储架构。

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可以获取属性的子集,是否仍需要关系索引实体来减少列表属性的序列化开销?
  2. 注意:投影查询有limits;关系指数实体没有。

    1. 关系索引实体是否会使查询更加困难?我想在过去7天内创建的帖子中过滤标签'cars'的帖子。 tags和post_date有不同的类型,有没有简单的方法呢?

    2. 关于爆炸索引,关系索引实体是否会降低爆炸索引的可能性,因为它将列表属性放在不同的类型中?

    3. 感谢您提前回答。

1 个答案:

答案 0 :(得分:1)

  1. Relation Index Entity解决方案减少了对<{1}}实体的任何类型访问的序列化开销,包括Post,`entity.put等操作)或者获取非投影查询,而投影查询仅用于获取相应的查询结果。

  2. 是的,查询有点困难。对于您的示例,您需要单独的查询,每个实体类型一个。

  3. 该示例假定使用key.get(),而不是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)
    
    1. 一般来说答案是肯定的,正是因为你提到的原因。在您的特定示例中,只有一个属性具有多个值 - 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属性,所有属性都具有单个值,因此爆炸索引影响的差异可能是不可忽视的。 / LI>

      将实体拆分为几个较小的实体也是一种常用的技术,例如,请参见re-using an entity's ID for other entities of different kinds - sane idea?

      这是在这里应用这个想法的一个例子:

      Post

      示例相当简单,可以使用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] 异步调用,任务/ tasklet,许多结果可能需要游标等来优化它们。