2

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

有没有更有效的方法来做到这一点,也许以某种方式将所有这些批处理到一个查询中?

4

2 回答 2

4

尝试查看 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)
于 2012-08-27T20:28:27.820 回答
1

您可以使用 ndb 异步方法同时执行这些查询:

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 个并发 Datastore Query RPC,总体延迟仅取决于最慢的一个,而不是所有延迟的总和

另请参阅官方ndb 文档以获取有关如何使用 ndb 异步 API 的更多详细信息。

于 2012-08-27T16:39:51.607 回答