说我有RootEntity
,AEntity
(RootEntity的孩子),BEntity
(AEntity
的孩子)。
class RootEntity(ndb.Model):
rtp = ndb.StringProperty()
class AEntity(ndb.Model):
ap = ndb.IntegerProperty()
class BEntity(ndb.Model):
bp = ndb.StringProperty()
因此,在不同的处理程序中,我需要使用特定的祖先(AEntity的实例)获取BEntity的实例。
我的查询有:BEntity.query(ancestor = ndb.Key("RootEntity", 1, "AEntity", AEntity.query(ancestor = ndb.Key("RootEntity", 1)).filter(AEntity.ap == int(some_value)).get().key.integer_id()))
如何优化此查询?让它更好,可能不那么复杂?
UPD:
此查询是@ndb.transactional
装饰器的函数的一部分。
答案 0 :(得分:2)
您不应使用实体组来表示实体关系。
Entity groups have a special purpose:定义交易范围。它们使您能够以事务方式更新多个实体,只要它们是同一实体组的一部分(使用新的XG transactions稍微放松了这个限制)。它们还允许您在事务中使用查询(不能通过XG事务获得)。
实体组的缺点是它们的更新限制为1次/秒。
在您的情况下,我的建议是使用单独的实体并在它们之间进行引用。引用应该是引用实体的Key,因为它是类型安全的。
关于查询简单性:遗憾的是GAE不支持JOIN或引用(多实体)查询,因此您仍然需要将多个查询组合在一起(就像现在一样)。
答案 1 :(得分:0)
祖先查询有一个给予和接受。它们处理起来更冗长,更麻烦,但您可以在查询中获得更好的数据结构和一致性。
为了简化这一点,如果您的处理程序知道您想要获得的BEntity,只需传递key.urlsafe()
编码密钥,它已经编码了所有祖先信息。
如果无法做到这一点,请尝试重新构建数据。由于这些对象都是相同的祖先,因此它们属于同一个实体组,因此最多可以为该实体组中的对象插入/更新~1次/秒。如果您需要更高的吞吐量或不需要一致的祖先查询,那么尝试使用ndb.KeyProperty
链接实体,引用父项而不是祖先。然后,您只需要让单个父母查询而不是父母和父母的父母。
您应该尽可能尝试使用ID,这样您就可以避免必须按属性过滤数据存储区中的实体,只需按ID引用它们:
BEntity.query(ancestor = ndb.Key("RootEntity", 1, "AEntity", int(some_value)))
此处,int(some_value)
是您在创建该对象时使用的AEntity
的整数ID。请确保您可以确保手动创建/使用的ID在共享同一父级的模型的所有实例中都是唯一的。
修改强>:
为了澄清,我的最后一个例子应该更清楚,因为我建议重构数据,使int(some_value)
用作AEntity
的整数ID而不是存储作为一个单独的属性实体 - 如果可能的话当然。从给出的示例中,对AEntity
个对象执行查询,这些对象具有给定的整数字段值int(some_value)
并使用get()
执行 - 这意味着您将始终期望单个值返回对于该整数ID,它可以作为该对象的键的整数ID使用,从而无需查询。