3

カーソルを使用してデータストアにクエリを実行する必要があります (タスクが 10 分以内に終了しない可能性があるため、カーソルが必要です)。これまでのところ、fetch_page または Query.iter() を使用して有効なカーソルを取得できませんでした。どちらの場合も、生成されたカーソルを使用すると、

BadRequestError: カーソル位置が元のクエリの範囲外です

ここにクエリがあります

qry = entity_type.query(ndb.AND(entity_type.application == "my_app",
                                ndb.OR(entity_type.status == 1,
                                       ndb.AND(entity_type.status == 0,
                                               entity_type.date >= start_date,
                                               entity_type.date < end_date))))

qry = qry.order(entity_type.date, entity_type._key)

オンライン ドキュメントで説明されているように、ndb.OR でフィルタリングし、モデルのキーでクエリを並べ替えていることに注意してください。

クエリを実行するコードは非常に簡単です

cursor = None
has_more = True
while has_more:       
    entities, cursor, more = qry.fetch_page(500,
                                            start_cursor=cursor,
                                            use_cache=False,
                                            use_memcache=False)
    # process the retrieved entities
    has_more  = cursor and more

最初のループは問題なく動作します (カーソルは None です)。2 番目のループ (カーソルが初期化される) で、エラーが発生します。私もイテレータでこれをやろうとしました:

cursor = None
has_more = True
while has_more:
    q_options = {"use_cache": False,
                 "use_memcache": False,
                 "produce_cursors": True}
    if cursor is not None:
        q_options["start_cursor"] = cursor

    q_iter = qry.iter(**q_options)
    entities = []
    for e in q_iter:
        entities.append(e)
        if len(entities) == 500:
            break

    more = q_iter.has_next()
    if more:
        cursor = q_iter.cursor_after()

    # process the retrieved entities
    has_more = cursor and more

同じ動作が見られます。現在、ndb.OR を 2 つの個別のクエリに分割する作業を行っています。それでも、ndb API を誤用しているのか、それとも別のものなのか疑問に思っています。

-- 更新 -- これがエラーのトレースです

W 05:00:09.171 suspended generator run_to_queue(query.py:938) raised BadRequestError(cursor position is outside the range of the original query)
W 05:00:09.762 suspended generator run_to_queue(query.py:1946) raised BadRequestError(cursor position is outside the range of the original query)
W 05:00:09.762 suspended generator run_to_queue(query.py:931) raised BadRequestError(cursor position is outside the range of the original query)
W 05:00:09.762 suspended generator helper(context.py:876) raised BadRequestError(cursor position is outside the range of the original query)
W 05:00:09.762 suspended generator has_next_async(query.py:1745) raised BadRequestError(cursor position is outside the range of the original query)
W 05:00:09.777 suspended generator _fetch_page_async(query.py:1349) raised BadRequestError(cursor position is outside the range of the original query)
E 05:00:09.777 cursor position is outside the range of the original query
  Traceback (most recent call last):
    [... some of my classes ...]
    File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/utils.py", line 142, in positional_wrapper
      return wrapped(*args, **kwds)
    File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/query.py", line 1331, in fetch_page
      return self.fetch_page_async(page_size, **q_options).get_result()
    File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 325, in get_result
      self.check_success()
    File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 368, in _help_tasklet_along
      value = gen.throw(exc.__class__, exc, tb)
    File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/query.py", line 1349, in _fetch_page_async
      while (yield it.has_next_async()):
    File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 368, in _help_tasklet_along
      value = gen.throw(exc.__class__, exc, tb)
    File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/query.py", line 1745, in has_next_async
      yield self._fut
    File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/context.py", line 876, in helper
      batch, i, ent = yield inq.getq()
    File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/query.py", line 931, in run_to_queue
      yield multiquery.run_to_queue(queue, conn, options=options)
    File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 368, in _help_tasklet_along
      value = gen.throw(exc.__class__, exc, tb)
    File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/query.py", line 1946, in run_to_queue
      thing = yield subit.getq()
    File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/query.py", line 938, in run_to_queue
      batch = yield rpc
    File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 454, in _on_rpc_completion
      result = rpc.get_result()
    File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/api/apiproxy_stub_map.py", line 613, in get_result
      return self.__get_result_hook(self)
    File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/datastore/datastore_query.py", line 2973, in __query_result_hook
      self._batch_shared.conn.check_rpc_success(rpc)
    File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/datastore/datastore_rpc.py", line 1342, in check_rpc_success
      raise _ToDatastoreError(err)
  BadRequestError: cursor position is outside the range of the original query
W 05:00:10.040 Found 1 RPC request(s) without matching response (presumably due to timeouts or other errors)
4

0 に答える 0