Минимизировать вложенные запросы с помощью in-запросов на AppEngine (python)

есть ли какой-либо умный способ избежать дорогостоящего запроса с предложением 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).

есть ли лучший способ сделать это (т. е. минимизация числа запросов)? Я понимаю, что нет никаких отношений и соединений с использованием хранилища данных, но, в частности, я бы рассмотрел возможность добавления новых полей в the User или Thing класс, если это помогает сделать вещи проще.

2 ответов


Я не думаю, что есть элегантное решение, но вы могли бы попробовать это:

в модели пользователя используйте 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)

это Google I/O talk Бретт Слаткин обращается к точной ситуации, с которой Вы имеете дело. См. также его последующие разговоры в этом году.