【问题标题】:Minimize subqueries with IN queries on AppEngine (python)在 AppEngine (python) 上使用 IN 查询最小化子查询
【发布时间】:2011-04-27 03:42:39
【问题描述】:

有什么聪明的方法可以避免在像下面这样的情况下使用 IN 子句进行代价高昂的查询?

我正在使用 Google App Engine 构建 Facebook 应用程序,并且在某些时候我(显然)需要查询数据存储区以获取属于给定用户的任何 Facebook 朋友的所有实体。

假设我有几个这样建模的实体:

class Thing(db.Model):
    owner = db.ReferenceProperty(reference_class=User, required=True)
    owner_id = db.StringProperty(required=True)
    ...

class User(db.Model):
    id = db.StringProperty(required=True)
    ...

在某些时候,我查询 Facebook 以获取给定用户的朋友列表,我需要执行以下查询

# get all Thing instances that belong to friends
query = Thing.all()
query.filter('owner_id IN', friend_ids)

如果我这样做了,AppEngine 将为friend_ids 中的每个 id 执行子查询,这可能超过任何查询可以产生的最大子查询数 (30)。

有没有更好的方法来做到这一点(即最小化查询数量)? 我知道没有使用数据存储的关系和连接,但特别是,如果有助于使事情变得更容易,我会考虑向 UserThing 类添加新字段。

【问题讨论】:

    标签: python google-app-engine google-cloud-datastore gql gquery


    【解决方案1】:

    Brett Slatkin 的This Google I/O talk 解决了您正在处理的确切情况。另请参阅今年的 his follow up talk

    【讨论】:

    【解决方案2】:

    我不认为有一个优雅的解决方案,但你可以试试这个:

    在 User 模型上,使用 Facebook ID 作为键名,并将每个用户的事物列表存储在 ListProperty 中。

    class Thing(db.Model):
      ...
    
    class User(db.Model):
      things = db.ListProperty(db.Key)
      ...
    

    实体创建过程如下:

    user = User.get_or_insert(my_facebook_id)
    
    thing = Thing()
    thing.put()
    
    user.things.append(thing.key())
    user.put()
    

    检索需要 2 个查询:

    friends = User.get_by_key_name(friend_ids)
    thing_keys = []
    
    for friend in friends:
      thing_keys.extend(friend.things)
    
    things = db.get(thing_keys)
    

    【讨论】:

    • +1 另一种选择是让 Things 成为 User 的子代,允许返回特定类型事物的祖先查询。 key_names 的使用对于真正起作用至关重要。
    • 太好了,我什至按照 kevpie 的建议为用户制作了 Things 子项。不过,我必须处理更多问题:a) 我没有为每个friend_id 存储用户实体,因此我需要过滤使用get_by_key_name 查询时获得的None 值; b)我还必须通过其他一些字段过滤掉东西,但是我在从 DataStore 获取它们之后对我获取的实体执行此操作。有没有更好的方法来做到这一点?
    • 请务必观看尼克在他的回答中发表的谈话。您可能希望将索引实体与列表属性结合使用。这在 Nick 发表的第一次演讲中有所体现。
    • 我正在尝试使用索引实体开发替代方案。使用 Facebook 好友列表作为参数执行 get_by_key_name 似乎对 DataStore 施加了太多压力。与每个用户关联的索引实体的问题是何时更新它们以使其与 Facebook 保持一致。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-25
    • 1970-01-01
    • 2011-10-27
    • 1970-01-01
    相关资源
    最近更新 更多