6

在以下情况下,是否有任何巧妙的方法可以避免使用 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 将为 中的每个 id 执行子查询friend_ids,可能超过任何查询可以产生的最大子查询数 (30)。

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

4

2 回答 2

5

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

在 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)
于 2010-10-18T21:29:24.380 回答
3

Brett Slatkin 的这个 Google I/O 演讲解决了您正在处理的确切情况。另见他今年的后续谈话。

于 2010-10-19T09:14:23.723 回答