Google应用引擎:更好的查询方式

时间:2015-01-20 15:38:28

标签: python google-app-engine python-2.7

说我有RootEntityAEntity(RootEntity的孩子),BEntityAEntity的孩子)。

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装饰器的函数的一部分。

2 个答案:

答案 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使用,从而无需查询。