如何获取数据存储查询的第n条记录
假设我在 GAE 上有一个叫 Foo 的模型,然后我有这样一个查询:
query = Foo.all().order('-key')
我想获取第 n 条记录。有什么最有效的方法可以做到这一点呢?
如果排序的属性不是唯一的,比如下面这个:
query = Foo.all().order('-color')
那么这个解决方案会出问题吗?
补充说明:n > 1000
再补充一下:我想开发一个友好的分页机制,能够显示可用的页面(比如第 1 页、第 2 页……第 185 页),并且在查询字符串中需要使用 "?page=x" 而不是 "?bookmark=XXX"。当 page = x 时,查询的目的是从该页面的第一条记录开始获取数据。
2 个回答
关于Query类的文档可以在这里找到:http://code.google.com/appengine/docs/python/datastore/queryclass.html#Query
这个查询类提供了一个叫做fetch的方法,它可以设置限制和偏移量,在你的情况下是1和n。
fetch的运行时间会随着偏移量和限制的增加而线性增长。
所以在你的情况下,优化的唯一方法就是确保你最常访问的记录尽量靠近数组的开头。
你可以使用以下代码:
query.filter('key = ', n)
query.get()
这样可以返回第一个匹配的键为n的记录。
其实没有什么高效的方法可以做到这一点,无论是什么数据库管理系统。在任何情况下,你至少得顺序读取索引记录,直到找到第n个,然后再查找对应的数据记录。这大致就是GAE中的fetch(count, offset)所做的事情,不过它有个额外的限制,就是最多只能处理1000条记录。
一个更好的方法是保持一个“书签”,这个书签包含你最后获取的实体的排序字段的值和实体的键。这样,当你想从上次停下的地方继续时,可以把这个字段的值作为查询的下限,然后跳过一些记录,直到找到你最后看到的那条记录或者超过它。
如果你想给用户提供“友好的”页面偏移量,你可以使用memcache来存储一个起始偏移量和书签(排序属性,键)之间的关联。当你生成一个页面时,插入或更新最后一个实体之后的书签。当你获取一个页面时,如果书签存在就用它,否则就得用比较麻烦的方法,通过偏移量进行查询——如果偏移量很高,可能需要进行多次查询。