使用AppEngine(python)上的IN查询最小化子查询

使用AppEngine(python)上的IN查询最小化子查询,python,google-app-engine,google-cloud-datastore,gql,gquery,Python,Google App Engine,Google Cloud Datastore,Gql,Gquery,在以下情况下,有没有聪明的方法避免使用IN子句进行代价高昂的查询 我正在使用Google App Engine构建一个Facebook应用程序,在某个时候我(显然)需要查询数据存储,以获取属于给定用户的任何Facebook好友的所有实体 假设我有两个这样建模的实体: class Thing(db.Model): owner = db.ReferenceProperty(reference_class=User, required=True) owner_id = db.Strin

在以下情况下,有没有聪明的方法避免使用IN子句进行代价高昂的查询

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

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

class Thing(db.Model):
    owner = db.ReferenceProperty(reference_class=User, required=True)
    owner_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\u ids
中的每个id执行子查询,可能超过任何查询可以生成的最大子查询数(30)

有没有更好的方法来做到这一点(即尽量减少查询数量)?
我知道使用DATASTORE没有关系和连接,但是,特别是,我会考虑将新字段添加到<代码>用户或Tys类,如果它有助于使事情变得更容易。

< P>我不认为有一个雅致的解决方案,但您可以尝试这样做:

在用户模型中,使用FacebookID作为键名,并将每个用户的列表存储在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)

作者Brett Slatkin讲述了你正在处理的确切情况。另见今年。

+1另一个选择是让Things子用户允许祖先查询要返回的特定类型的东西。使用key_名称对这项工作非常重要。这太棒了,我甚至按照kevpie的建议为用户制作了一些小东西。不过,我还需要处理几个问题:a)我没有为每个friend_id存储用户实体,因此我需要过滤使用get_by_key_name查询时得到的None值;b) 我还必须通过一些其他字段过滤掉一些内容,但我是在从数据存储中获取实体后对它们进行过滤的。有没有更好的方法呢?一定要看尼克在回答中发表的谈话。您可能希望将索引实体与列表属性结合使用。这在Nick发表的第一篇演讲中就有体现。我正在尝试使用索引实体开发替代方案。使用Facebook好友列表作为参数来执行get_by_key_name似乎有点过分强调了数据存储。与每个用户相关联的索引实体的问题在于何时更新它们以使它们与Facebook保持一致。恐怕你在上一次谈话中发布了两次相同的链接。你是指这个吗?
friends = User.get_by_key_name(friend_ids)
thing_keys = []

for friend in friends:
  thing_keys.extend(friend.things)

things = db.get(thing_keys)