当请求第一页时,获取前5个条目。对于第二页,获取接下来的5个条目,以此类推。
我计划使用couchdb-python模块实现,但这不应影响实现。
CouchDB Guide对于分页有一个很好的讨论,包括很多示例代码,在这里:http://guide.couchdb.org/draft/recipes.html#pagination
rows_per_page + 1
行数据。rows_per_page
行数据,并将最后一行保存为next_startkey
。startkey
和next_startkey
。next_*
值创建下一页链接,使用其他值创建上一页链接。注意:在CouchDB中获取页面的正确方法是通过指定起始键而不是起始索引。但是如何知道第二页应该从哪个键开始呢?巧妙的解决方案是:“不是请求一页10行数据,而是请求11行数据,只显示其中的10行,并使用第11行的值作为下一页的起始键。”
如果您希望多个文档发出相同的键,则还需要使用startdocid
来正确分页。原因是仅使用startkey
将不再足以唯一标识一行。如果您不提供startkey
,则这些参数将无用。实际上,CouchDB首先查看startkey
参数,然后如果多个潜在的起始行具有相同的键但具有不同的文档ID,则使用startdocid
参数进一步重新定义范围的开始。对于enddocid
也是同样的情况。
CouchDB的HTTP View API提供了充分的支持以高效地进行分页。
最简单的方法是使用startkey
和count
。Count是CouchDB将为该视图请求返回的最大条目数,这取决于您的设计,而startkey则是您希望CouchDB开始的位置。当您请求视图时,它还会告诉您有多少条目,让您可以计算出有多少页(如果您想向用户展示的话)。
因此,第一个请求不会指定startkey,只是指定要显示的条目数计数。然后您可以记录返回的最后一个条目的键,并将其用作下一页的起始键。在这个简单的形式中,您会得到一个重叠,其中一个页面的最后一个条目是下一个页面的第一个条目。如果这不是您想要的,那么简单地不显示页面最后一条目即可。
另一种更简单的方法是使用skip参数来确定页面的起始文档,但应谨慎使用此方法。skip参数仅仅是导致内部引擎不返回正在迭代的条目。虽然这会产生期望的行为,但比通过关键字找到页面的第一个文档要慢得多。跳过的文档数越多,请求速度就会越慢。
目前为止,这是我想出来的方法——获取所有帖子的ID,然后检索前x个ID的实际项目。
虽然不是非常高效,但比检索所有帖子然后将大多数帖子丢掉要好得多。话虽如此,令我惊讶的是,它似乎运行得相当快——我运行了100次posthelper.page()
方法,只用了大约0.5秒。
我不想在实际问题中发布这篇文章,因为这样会对答案产生更大的影响——这是代码:
allPostsUuid = """
function(doc) {
if(doc.type == 'post'){
emit(doc._id, null);
}
}
"""
class PostsHelper:
def __init__(self):
server = Server(config.dbhost)
db = server[config.dbname]
return db
def _getPostByUuid(self, uuid):
return self.db.get(uuid)
def page(self, number = 1):
number -= 1 # start at zero offset
start = number * config.perPage
end = start + config.perPage
allUuids = [
x.key for x in self.db.query(allPostsUuid)
]
ret = [
self._getPostByUuid(x) for x in allUuids[start : end]
]
if len(ret) == 0:
raise Error404("Invalid page (%s results)" % (len(allUuids)))
else:
return ret
var lastOffset = 0; var counter = 0;
function someRecursive(lastOffset,counter) {
queryView(db, whereClause).then(result => {
var rows_per_page = 5;
//formula below
var page = Math.floor((lastOffset == 0 ? 0: (result.offset - lastOffset) +
(rows_per_page * counter)) / rows_per_page) + 1;
var skip = page * rows_per_page;
if (somerecursionexitcondition) {
counter = lastOffset == 0 ? lastOffset: counter + 1;
lastOffset =result.offset;
someRecursive(lastOffset, counter).then(result => {
resolve();
});
});
}
_id
推入数组中,您可以在单击“上一页”时轻松地pop()
数组_id
。最多只需要跟踪整数数组即可。 - wootencl