Pagination CouchDB中的分页?

Pagination CouchDB中的分页?,pagination,couchdb,Pagination,Couchdb,如何实现分页所需的查询 基本上,当请求第1页时,获取前5个条目。对于第2页,获取下一个5,依此类推 我计划通过couchdb python模块使用它,但这不会对实现造成任何影响。这就是我到目前为止提出的方法-获取所有帖子的ID,然后检索前x个ID的实际项目 这并不十分有效,但比检索所有帖子,然后扔掉大部分帖子更有效。这就是说,令我惊讶的是,它似乎运行得相当快——我运行了posthelper.page()方法100次,耗时约0.5秒 我不想在实际问题中发表这一点,因此它不会对答案产生太大影响-以下

如何实现分页所需的查询

基本上,当请求第1页时,获取前5个条目。对于第2页,获取下一个5,依此类推


我计划通过couchdb python模块使用它,但这不会对实现造成任何影响。

这就是我到目前为止提出的方法-获取所有帖子的ID,然后检索前x个ID的实际项目

这并不十分有效,但比检索所有帖子,然后扔掉大部分帖子更有效。这就是说,令我惊讶的是,它似乎运行得相当快——我运行了
posthelper.page()
方法100次,耗时约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
CouchDB提供了大量有效地进行分页的空间

最简单的方法是使用
startkey
count
。Count是CouchDB将为该视图请求返回的最大条目数,这取决于您的设计,startkey是您希望CouchDB开始的地方。当您请求查看时,它还将告诉您有多少条目,允许您计算有多少页面,如果您想向用户显示

因此,第一个请求不会指定startkey,只指定要显示的条目数。然后,您可以记下返回的最后一个条目的键,并将其用作下一页的开始键。在这个简单的表单中,您将得到一个重叠,其中一个页面的最后一个条目是下一个页面的第一个条目。如果不希望这样做,那么不显示页面的最后一个条目就很简单了

一种更简单的方法是使用skip参数计算页面的起始文档,但是使用此方法时应小心。skip参数只会导致内部引擎不返回它正在迭代的条目。虽然这提供了所需的行为,但比按键查找页面的第一个文档要慢得多。跳过的文档越多,请求的速度就越慢。

对分页进行了很好的讨论,包括大量示例代码,如下所示: 这是他们的算法:

  • 从视图中请求每页
    行+1
  • 每页显示
    行,将最后一行存储为
    next\u startkey
  • 作为页面信息,保留
    startkey
    next\u startkey
  • 使用
    next.*
    值创建下一个链接,使用其他值创建上一个链接
注意:在CouchDB中获取页面的正确方法是指定一个起始键,而不是像你想象的那样指定一个起始索引。但是你怎么知道第二页的开始键呢?聪明的解决方案是:“不要为一页请求10行,而是请求11行,但只显示10行,并使用第11行中的值作为下一页的开始键。”

如果希望多个文档发出相同的键,则除了使用
startkey
外,还需要使用
startCID
来正确分页。原因是单独的
startkey
将不再足以唯一标识行。如果不提供
startkey
,这些参数将无效。实际上,CouchDB将首先查看
startkey
参数,然后如果多个可能的起始行具有相同的键但不同的文档ID,它将使用
startdocid
参数进一步重新定义范围的开始。对于
enddocid

  • 下面是我发现的递归方法:

    取两个变量


啊哈!从您链接的页面:count参数可以与“skip=要跳过的行数”组合。太好了。我已经在你的答案中添加了上述信息(如果没有其他信息,请参考),希望你不介意!我又编辑了一遍。在大多数情况下,使用skip不是一种很好的方法。不,要找到第n个条目,您需要遍历索引树,因为您不知道树中的分支有多少个条目。你可以更快地找到一个特定的键。查看你发布的链接,我发现没有“计数”选项。而是有一个“限制”选项。也许它被改变了?这个方法的问题是你不能多次点击前一个,只能点击一次。当你转到下一页时,你必须手动索引所有可能的第一页,或者你只能返回一页,然后你没有任何信息可以进入另一页。对于那些在这里遇到困难并且也遇到@for3st困境的人,数组的自然特性有助于解决这个问题。通过
push()
将上一页开始
\u id
插入数组,您可以在单击“上一页”时轻松地
pop()
数组
\u id
。最多你要做的就是跟踪一个整数数组。
  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();

                           });
  });

  }