NDB 游标不记得一些查询数据?

NDB cursors not remembering some query data?

所以,我有这个查询:

results, cursor, more = MyModel.query(
    ancestor=mykey,
).order(-MyModel.time).fetch_page(20)

到目前为止一切顺利,返回的数据很好等。现在,让我们再获取一些,好吗?这样做似乎合乎逻辑:

results, cursor, more = MyModel.query() \
    .order(-MyModel.time) \
    .fetch_page(20, start_cursor=Cursor(urlsafe=request.cursor))

而且...奇怪的事情发生了。绝对太多的结果,无序的结果......这是怎么回事? 所以我将其更改为:

results, cursor, more = MyModel.query(ancestor=mykey) \
    .order(-MyModel.time) \
    .fetch_page(20, start_cursor=Cursor(urlsafe=request.cursor))

突然间,wat less results...让我们添加

.order(-MyModel.time)

我得到了我期望的结果。

现在...我在这里遗漏了什么吗?传递游标不应该已经处理好排序和祖先吗?文档中有用于获取初始页面的排序示例 - https://cloud.google.com/appengine/docs/python/ndb/queries#cursors - 但没有任何地方说后续页面也需要设置排序。我只想知道,这是否真的按预期工作,或者这是一个错误?

如果它确实按预期工作,是否有任何地方可以让我了解游标中究竟存储了哪些信息?将来避免此类错误真的很有帮助。

来自 Query Cursors(我的重点):

A query cursor is a small opaque data structure representing a resumption point in a query. This is useful for showing a user a page of results at a time; it's also useful for handling long jobs that might need to stop and resume. A typical way to use them is with a query's fetch_page() method. It works somewhat like fetch(), but it returns a triple (results, cursor, more). The returned more flag indicates that there are probably more results; a UI can use this, for example, to suppress a "Next Page" button or link. To request subsequent pages, pass the cursor returned by one fetch_page() call into the next.

游标仅存在于(并且有意义)生成它的原始查询的上下文中,您不能使用在一个查询(在您的情况下为祖先查询)的上下文中生成的游标来导航来自另一个查询(您的非祖先查询)的结果。我的意思是它可能不会呕吐(正如你的实验所证明的那样)但结果可能不是你所期望的:)

从根本上说,游标只是表示查询结果列表中的当前位置(如果需要,可以是索引)。在其他一些列表中使用该索引可能不会崩溃,但也没有多大意义(除非专门设计用于)。

使用变量存储查询以供重复使用而不是每次都重新构建它可能是一个好习惯,以避免此类意外错误。如该文档的 snippets.py 示例所示:

# Set up.
q = Bar.query()
q_forward = q.order(Bar.key)
q_reverse = q.order(-Bar.key)

# Fetch a page going forward.
bars, cursor, more = q_forward.fetch_page(10)

# Fetch the same page going backward.
r_bars, r_cursor, r_more = q_reverse.fetch_page(10, start_cursor=cursor)

旁注:此示例实际上使用一个查询中的游标来导航另一个查询中的结果,但是这 2 个查询被设计为 "compatible".