Python版では、Query.run()を使うと非同期呼び出しができる。
例えば Diary というモデルがあったとして:
q = Diary().filter(...)
iterator = q.run()
このようにしてrunメソッドを呼び出すと、
裏では非同期にAPIが呼び出される。
runの戻り値はイテレータであり、
これを使おうとしたときに結果の待ち合わせが行われる。
よって、イテレータを使わないでおいて、
他のQuery.run()を呼び出せば、複数のAPIが並列にできる:
diary_query = Diary().filter(...)
diary_iterator = diary_query.run()
comment_query = Comment().filter(...)
comment_iterator = comment_query.run()
#これ以降でdiary_iterator,comment_iteratorを使う
Query.run()はイテレータを返すので、
Query.fetch()のようにlimitを指定できない。
そのままイテレーションすると、結果と時間の許す限り、
ずっとイテレーションしてしまう。
limitを指定したければイテレーション中に件数をカウント
すればいいが、面倒なので、自前のイテレータでラップする。
class QueryIterator(object):
def __init__(self, query, limit=None):
self.limit = limit
self.count = 0
if limit:
config = datastore_query.QueryOptions(limit=limit, prefetch_size=limit)
else:
config = None
self.iterator = query.run(config=config)
def __iter__(self):
return self
def next(self):
if self.limit and self.limit <= self.count:
raise StopIteration()
self.count += 1
return self.iterator.next()
def get_result(self):
return [e for e in self]
これを使うと:
q = Diary().filter(...)
iterator = QueryIterator(q, limit=100)
for entity in iterator:
...
# 第一引数がq.run()じゃないことに注意
このイテレータは指定された件数に達するとイテレーションを終えるので、
際限なく処理が続いてしまうことはなくなる。
また、結果をリストで欲しい時は:
q = Diary().filter(...)
iterator = QueryIterator(q, limit=100)
entities = iterator.get_result()
のように使える。
0 件のコメント:
コメントを投稿