减少AppEngine(Python)中IN查询的子查询数量

6 投票
2 回答
1323 浏览
提问于 2025-04-16 05:42

有没有什么聪明的方法可以避免在像下面这种情况下进行代价高昂的查询,特别是使用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)

如果我这样做,App Engine会对friend_ids中的每个ID执行一个子查询,这可能会超过任何查询可以产生的最大子查询数量(30个)。

有没有更好的方法来做到这一点(也就是说,尽量减少查询的数量)?我知道在数据存储中没有关系和连接,但如果能让事情变得更简单,我考虑在UserThing类中添加新字段。

2 个回答

3

这段话提到的是Brett Slatkin在Google I/O大会上的一个演讲,内容正好和你现在遇到的问题有关。你还可以看看他今年的后续演讲

5

我觉得没有特别优雅的解决办法,但你可以试试这个:

在用户模型中,使用Facebook ID作为关键名称,并把每个用户的物品列表存储在一个列表属性里。

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()

获取数据需要进行两次查询:

friends = User.get_by_key_name(friend_ids)
thing_keys = []

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

things = db.get(thing_keys)

撰写回答