给定 NDB 游标,获取上一页结果的正确方法是什么? [英] What is the correct way to get the previous page of results given an NDB cursor?

查看:17
本文介绍了给定 NDB 游标,获取上一页结果的正确方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正致力于通过 GAE 提供一个 API,该 API 将允许用户通过一组实体向前和向后翻页.我已经查看了 有关 NDB 查询文档页面上的游标的部分,其中包含一些示例代码,描述了如何通过查询结果向后翻页,但它似乎没有按预期工作.我使用的是 GAE 开发 SDK 1.8.8.

I'm working on providing an API via GAE that will allow users to page forwards and backwards through a set of entities. I've reviewed the section about cursors on the NDB Queries documentation page, which includes some sample code that describes how to page backwards through query results, but it doesn't seem to be working as desired. I'm using GAE Development SDK 1.8.8.

这是该示例的修改版本,它创建了 5 个示例实体,获取并打印第一页,向前进入并打印第二页,然后尝试向后移动并再次打印第一页:

Here's a modified version of that example that creates 5 sample entities, gets and prints the first page, steps forward into and prints the second page, and attempts to step backwards and print the first page again:

import pprint
from google.appengine.ext import ndb

class Bar(ndb.Model):
    foo = ndb.StringProperty()

#ndb.put_multi([Bar(foo="a"), Bar(foo="b"), Bar(foo="c"), Bar(foo="d"), Bar(foo="e")])

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

# Fetch the first page.
bars1, cursor1, more1 = q_forward.fetch_page(2)
pprint.pprint(bars1)

# Fetch the next (2nd) page.
bars2, cursor2, more2 = q_forward.fetch_page(2, start_cursor=cursor1)
pprint.pprint(bars2)

# Fetch the previous page.
rev_cursor2 = cursor2.reversed()
bars3, cursor3, more3 = q_reverse.fetch_page(2, start_cursor=rev_cursor2)
pprint.pprint(bars3)

(仅供参考,您可以在本地应用引擎的交互式控制台中运行上述内容.)

(FYI, you can run the above in the Interactive Console of your local app engine.)

以上代码打印结果如下;注意第三页结果只是倒转了第二页,而不是回到第一页:

The above code prints the following results; note that the third page of results is just the second page reversed, instead of going back to the first page:

[Bar(key=Key('Bar', 4996180836614144), foo=u'a'),
 Bar(key=Key('Bar', 6122080743456768), foo=u'b')]
[Bar(key=Key('Bar', 5559130790035456), foo=u'c'),
 Bar(key=Key('Bar', 6685030696878080), foo=u'd')]
[Bar(key=Key('Bar', 6685030696878080), foo=u'd'),
 Bar(key=Key('Bar', 5559130790035456), foo=u'c')]

我期待看到这样的结果:

I was expecting to see results like this:

[Bar(key=Key('Bar', 4996180836614144), foo=u'a'),
 Bar(key=Key('Bar', 6122080743456768), foo=u'b')]
[Bar(key=Key('Bar', 5559130790035456), foo=u'c'),
 Bar(key=Key('Bar', 6685030696878080), foo=u'd')]
[Bar(key=Key('Bar', 6685030696878080), foo=u'a'),
 Bar(key=Key('Bar', 5559130790035456), foo=u'b')]

如果我将代码的获取上一页"部分更改为以下代码片段,我会得到预期的输出,但是是否有任何我没有预见到使用前向查询和 end_cursor 而不是文档中描述的机制?

If I change the "Fetch the previous page" section of code to the following code snippet, I get the expected output, but are there any drawbacks that I haven't forseen to using the forward-ordered query and end_cursor instead of the mechanism described in the documentation?

# Fetch the previous page.
bars3, cursor3, more3 = q_forward.fetch_page(2, end_cursor=cursor1)
pprint.pprint(bars3)

推荐答案

为了使文档中的示例更清晰,让我们暂时忘记数据存储并使用列表:

To make the example from the docs a little clearer let's forget about the datastore for a moment and work with a list instead:

# some_list = [4, 6, 1, 12, 15, 0, 3, 7, 10, 11, 8, 2, 9, 14, 5, 13]

# Set up.
q = Bar.query()

q_forward = q.order(Bar.key)
# This puts the elements of our list into the following order:
# ordered_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]

q_reverse = q.order(-Bar.key)
# Now we reversed the order for backwards paging: 
# reversed_list = [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

# Fetch a page going forward.

bars, cursor, more = q_forward.fetch_page(10)
# This fetches the first 10 elements from ordered_list(!) 
# and yields the following:
# bars = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# cursor = [... 9, CURSOR-> 10 ...]
# more = True
# Please notice the right-facing cursor.

# Fetch the same page going backward.

rev_cursor = cursor.reversed()
# Now the cursor is facing to the left:
# rev_cursor = [... 9, <-CURSOR 10 ...]

bars1, cursor1, more1 = q_reverse.fetch_page(10, start_cursor=rev_cursor)
# This uses reversed_list(!), starts at rev_cursor and fetches 
# the first ten elements to it's left:
# bars1 = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

因此文档中的示例以两种不同的顺序从两个不同的方向获取同一页面.这不是您想要实现的目标.

So the example from the docs fetches the same page from two different directions in two differents orders. This is not what you want to achieve.

您似乎已经找到了一个可以很好地涵盖您的用例的解决方案,但让我建议另一个:

It seems you already found a solution that covers your use case pretty well but let me suggest another:

只需重用 cursor1 即可返回 page2.
如果我们说的是前端并且当前页面是 page3,这意味着将 cursor3 分配给next"按钮,将 cursor1 分配给previous"按钮.

Simply reuse cursor1 to go back to page2.
If we're talking frontend and the current page is page3, this would mean assigning cursor3 to the 'next'-button and cursor1 to the 'previous'-button.

这样你就不必反转查询和游标.

That way you have to reverse neither the query nor the cursor(s).

这篇关于给定 NDB 游标,获取上一页结果的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆