简体   繁体   English

Google App Engine:更好的查询方式

[英]Google app engine: better way to make query

Say I have RootEntity , AEntity (child of RootEntity), BEntity (child of AEntity ). 假设我有RootEntityAEntity (RootEntity的子代), BEntityAEntity )。

class RootEntity(ndb.Model):
    rtp = ndb.StringProperty()

class AEntity(ndb.Model):
    ap = ndb.IntegerProperty()

class BEntity(ndb.Model):
    bp = ndb.StringProperty()

So in different handlers I need to get instances of BEntity with specific ancestor(instance of AEntity). 因此,在不同的处理程序中,我需要获取具有特定祖先(AEntity的实例)的BEntity的实例。

There is a my query: 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())) 我有一个查询: 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()))

How I can to optimize this query? 如何优化此查询? Make it better, may be less sophisticated? 使它变得更好,可能不会那么复杂?

Upd: 更新:

This query is a part of function with @ndb.transactional decorator. 该查询是@ndb.transactional装饰器函数的一部分。

You should not use Entity Groups to represent entity relationships. 您不应使用实体组来表示实体关系。

Entity groups have a special purpose : to define the scope of transactions. 实体组有一个特殊目的 :定义交易范围。 They give you ability to update multiple entities transactionally, as long as they are a part of the same entity group (this limitation has been somewhat relaxed with the new XG transactions ). 只要它们是同一实体组的一部分,它们就使您能够以事务方式更新多个实体(此限制在新的XG事务中已得到放松)。 They also allow you to use queries within transactions (not available via XG transactions). 它们还允许您在事务内使用查询(无法通过XG事务使用)。

The downside of entity groups is that they have an update limitation of 1 write/second. 实体组的缺点是它们的更新限制为1个写入/秒。

In your case my suggestion would be to use separate entities and make references between them. 在您的情况下,我的建议是使用单独的实体并在它们之间进行引用。 The reference should be a Key of the referenced entity as this is type-safe. 引用应该是被引用实体的键,因为这是类型安全的。

Regarding query simplicity: GAE unfortunately does not support JOINs or reference (multi-entity) queries, so you would still need to combine multiple queries together (as you do now). 关于查询的简单性:不幸的是,GAE不支持JOIN或引用(多实体)查询,因此您仍然需要将多个查询组合在一起(就像现在一样)。

There is a give and take with ancestor queries. 祖先查询是有条件的。 They are a more verbose and messy to deal with but you get a better structure to your data and consistency in your queries. 它们处理起来比较冗长和混乱,但是您的数据结构和查询的一致性更好。

To simplify this, if your handler knows the BEntity you want to get, just pass around the key.urlsafe() encoded key, it already has all of your ancestor information encoded. 为了简化此操作,如果您的处理程序知道您想要获取的BEntity,则只需传递key.urlsafe()编码的密钥,它就已经对您的所有祖先信息进行了编码。

If this is not possible, try possibly restructuring your data. 如果不可能,请尝试重组数据。 Since these objects are all of the same ancestor, they belong to the same entity group, thus at most you can insert/update ~1 time per second for objects in that entity group. 由于这些对象都是同一祖先,因此它们属于同一实体组,因此,您最多可以每秒为该实体组中的对象插入/更新〜1次。 If you require higher throughput or do not require consistent ancestral queries, then try using ndb.KeyProperty to link entities with a reference to a parent rather than as an ancestor. 如果您需要更高的吞吐量或不需要一致的祖先查询,请尝试使用ndb.KeyProperty链接具有对父代而不是祖先的引用的实体。 Then you'd only need to get a single parent to query on rather than the parent and the parent's parent. 然后,您只需要让单亲查询即可,而不是父查询和父查询。

You should also try and use IDs whenever possible, so you can avoid having to filter for entities in your datastore by properties and just reference them by ID: 您还应该尽可能尝试使用ID,这样就可以避免必须按属性过滤数据存储中的实体,而不必按ID进行引用:

BEntity.query(ancestor = ndb.Key("RootEntity", 1, "AEntity", int(some_value)))

Here, int(some_value) is the integer ID of the AEntity you used when you created that object. 在这里, int(some_value)是创建该对象时使用的AEntity的整数ID。 Just be sure that you can ensure the IDs you manually create/use will be unique across all instances of that Model that share the same parent. 只要确保您可以确保手动创建/使用的ID在该Model的所有共享相同父代的实例中都是唯一的即可

EDIT : To clarify, my last example should have been made more clear in that I was suggesting to restructure the data such that int(some_value) be used as the integer ID of the AEntity rather than storing is as a separate property of the Entity - if possible of course. 编辑 :为了澄清,我的最后一个例子应该已经变得更加清楚,我是暗示改组数据,使得int(some_value)被用作的整数ID AEntity而不是存储是作为实体的一个单独的属性-如果可能的话。 From the example given, a query is performed for the AEntity objects that have a given integer field value of int(some_value) and executed with a get() - implying that you will always expect a single value return for that integer ID making it a good candidate to use as the integer ID for the key of that object eliminating the need for a query. 从给出的示例中, AEntity具有给定整数字段值int(some_value)AEntity对象执行查询,并使用get()执行-这意味着您将始终希望获得该整数ID的单个值返回,从而使其成为很好的候选对象,用作该对象键的整数ID,无需查询。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM