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

时间:2010-10-18 20:16:33

标签: 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.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类添加新字段,如果它有助于简化操作。

2 个答案:

答案 0 :(得分:5)

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

在用户模型上,使用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 :(得分:3)

Brett Slatkin的

This Google I/O talk解决了你正在处理的确切情况。另见今年his follow up talk