我正在为经典的“用户帖子”和“标签”问题设计谷歌数据存储模式。
这个页面建议建立关系索引实体模型。基本上,它将可搜索的标记或关键字作为子实体中的列表属性进行过滤,在父实体中放置必要的属性。据我理解,这种方法是减少查询时的序列化开销。
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)注意:投影查询有限制;关系索引实体没有。
谢谢你提前回答。
发布于 2017-03-01 06:27:38
Post实体的访问,包括key.get()、`entity.put()或获取非投影查询之类的操作,而投影查询只用于获取相应的查询结果。该示例假设使用的是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 --以及少量其他Post属性,所有这些属性都具有单个值,因此爆炸索引影响的差异可能是可以忽略的。将一个实体拆分成几个较小的实体也是一种常见的技术,因为还有其他原因,例如,请参见为其他不同类型的实体重新使用实体的ID -明智的想法?。
这里有一个应用这个想法的例子:
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异步调用、任务/线程、许多结果可能需要游标等对它们进行优化。
https://stackoverflow.com/questions/42523602
复制相似问题