Эффективный способ запроса в цикле for в Google App Engine?

В документации GAE говорится:

Поскольку каждая операция get () или put () вызывает отдельный удаленный вызов процедуры (RPC), выдача многих таких вызовов внутри цикла является неэффективным способом обработки коллекции сущностей или ключей одновременно.

Кто знает, сколько других неэффективности у меня в моем коде, поэтому я хотел бы свести к минимуму столько, сколько смогу. В настоящее время у меня есть цикл for, где каждая итерация имеет отдельный запрос. Предположим, у меня есть Пользователь, и у пользователя есть друзья. Я хочу получать последние обновления для каждого друга пользователя. Итак, у меня есть массив друзей этого пользователя:

for friend_dic in friends: email = friend_dic['email'] lastUpdated = friend_dic['lastUpdated'] userKey = Key('User', email) query = ndb.gql('SELECT * FROM StatusUpdates WHERE ANCESTOR IS :1 AND modifiedDate > :2', userKey, lastUpdated) qit = query.iter() while (yield qit.has_next_async()): status = qit.next() status_list.append(status.to_dict()) raise ndb.Return(status_list) 

Есть ли более эффективный способ сделать это, возможно, каким-то образом пакет все это в один запрос?

2 Solutions collect form web for “Эффективный способ запроса в цикле for в Google App Engine?”

Попробуйте найти функцию карты NDB: https://developers.google.com/appengine/docs/python/ndb/queryclass#Query_map_async

Пример (предполагая, что вы поддерживаете отношения своих друзей в отдельной модели, для этого примера я предположил модель Relationships ):

 @ndb.tasklet def callback(entity): email = friend_dic['email'] lastUpdated = friend_dic['lastUpdated'] userKey = Key('User', email) query = ndb.gql('SELECT * FROM StatusUpdates WHERE ANCESTOR IS :1 AND modifiedDate > :2', userKey, lastUpdated) status_updates = yield query.fetch_async() raise ndb.Return(status_updates) qry = ndb.gql("SELECT * FROM Relationships WHERE friend_to = :1", user.key) updates = yield qry.map_async(callback) #updates will now be a list of status updates 

Обновить:

С лучшим пониманием вашей модели данных:

 queries = [] status_list = [] for friend_dic in friends: email = friend_dic['email'] lastUpdated = friend_dic['lastUpdated'] userKey = Key('User', email) queries.append(ndb.gql('SELECT * FROM StatusUpdates WHERE ANCESTOR IS :1 AND modifiedDate > :2', userKey, lastUpdated).fetch_async()) for query in queries: statuses = yield query status_list.extend([x.to_dict() for x in statuses]) raise ndb.Return(status_list) 

Вы можете выполнять эти запросы одновременно с помощью nintable-асинхронных методов:

 from google.appengine.ext import ndb class Bar(ndb.Model): pass class Foo(ndb.Model): pass bars = ndb.put_multi([Bar() for i in range(10)]) ndb.put_multi([Foo(parent=bar) for bar in bars]) futures = [Foo.query(ancestor=bar).fetch_async(10) for bar in bars] for f in futures: print(f.get_result()) 

Это запускает 10 параллельных RPC-запросов Datastore Query, и общая латентность зависит только от самого медленного, а не от суммы всех задержек

Также см. Официальную документацию ndb для более подробной информации о том, как асинхронные API с ndb.

  • Как мы можем проверить, установлено ли наше приложение для некоторых организаций, но не для всех?
  • Модули GAE и конечные точки Google
  • Android Studio: IncorrectOperationException при нажатии кнопки «Добавить в библиотеку» при попытке настроить клиентские библиотеки конечных точек Google Apps
  • нет приемлемого компилятора C, найденного в $ PATH на Google compute engine
  • GAE - Как жить без объединений?
  • Как настроить flex crossdomain.xml в Python Google App Engine Sdk
  • Проверка подписки на сообщение о покупке приложения для Android в Python в Google App Engine
  • Интернационализация с помощью python gae, babel и i18n. Не удается вывести правильную строку
  • Python - лучший язык программирования в мире.