Google App Engine如何高效查询指定父键列表中存在子实体的父级
高效查询方案
下面是两种无额外性能浪费的可行方案,均不需要拉取子实体的全部非必要属性:
方案1:带distinct=True的投影查询(适配当前实体定义,成本最低)
你遇到的投影字段和过滤字段冲突的问题,只需要给投影查询添加distinct=True参数即可绕过,该方案只会读取parent_key这一个索引字段,不会加载其他属性,性能和拉全量实体相比有数量级提升:
# 注意IN操作符单次最多支持30个值,若parents_list长度超过30需拆分分批查询 children_list = Child.query(Child.parent_key.IN(parents_list)).fetch( projection=[Child.parent_key], distinct=True ) # 对结果去重,得到所有存在子实体的父级键 has_child_parents = list({c.parent_key for c in children_list})
方案2:优化实体设计适配高频查询(适合读多写少场景)
如果该查询是业务高频操作,可以调整实体设计进一步提升查询效率:
调整1:使用祖先关系关联父子实体
将Child实体的父级设为Parent实体的键作为祖先路径,无需单独设置parent_key属性:
class Child(ndb.Model): # 无需单独定义parent_key,父级关系通过实体键的祖先路径存储 ... 其他属性 ...
这种场景下可以直接使用成本最低的keys_only查询,不需要读取任何实体属性:
# 批量查询的话拆分parents_list分批处理即可 has_child_parents = [p for p in parents_list if Child.query(ancestor=p).get(keys_only=True) is not None]
调整2:给Parent实体加标记字段
给Parent实体新增带索引的has_child布尔字段,在新增/删除Child实体时同步更新对应父级的标记值,后续直接查询父级即可:
class Parent(ndb.Model): has_child = ndb.BooleanProperty(indexed=True, default=False) # 后续查询直接走父级索引,延迟更低 has_child_parents = Parent.query( Parent.key.IN(parents_list), Parent.has_child == True ).fetch(keys_only=True)
内容的提问来源于stack exchange,提问作者OlivierM
相关产品推荐
相关产品推荐

