CouchDB中的分页?

时间:2008-11-23 05:37:17

标签: pagination couchdb

我如何实现分页所需的查询?

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

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

4 个答案:

答案 0 :(得分:31)

CouchDB Guide对分页进行了很好的讨论,包括大量示例代码,在这里:http://guide.couchdb.org/draft/recipes.html#pagination 这是他们的算法:

  • 从视图中请求rows_per_page + 1
  • 显示rows_per_page行,将最后一行存储为next_startkey
  • 作为页面信息,请保留startkeynext_startkey
  • 使用next_*值创建下一个链接,并使用其他链接创建上一个链接

N.B。:在CouchDB中获取页面的正确方法是指定一个起始键,而不是像你想象的那样的起始索引。但是你怎么知道开始第2页的关键是什么?聪明的解决方案:“不是为页面请求10行,而是请求11行,但只显示10行,并使用第11行中的值作为下一页的开始键。”

如果您希望多个文档发出相同的密钥,除了startdocid之外,您还需要使用startkey来正确分页。原因是单独startkey将不再足以唯一地标识行。如果您不提供startkey,那么这些参数将毫无用处。事实上,CouchDB将首先查看startkey参数,然后如果多个潜在的凝视行具有相同的密钥但文档ID不同,它将使用startdocid参数进一步重新定义范围的开头。同样适用于enddocid

答案 1 :(得分:13)

CouchDB HTTP View API提供了足够的范围来有效地进行分页。

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

因此第一个请求不会指定启动键,只会指定要显示的条目数。然后,您可以记下返回的最后一个条目的键,并将其用作下一页的开始键。在这个简单的表单中,您将获得重叠,其中一个页面的最后一个条目是下一个页面的第一个条目。如果这不可取,那么简单地不显示页面的最后一个条目就是微不足道的。

更简单的方法是使用skip参数计算页面的起始文档,但是应谨慎使用此方法。 skip参数只是导致内部引擎不返回它正在迭代的条目。虽然这给出了期望的行为,但它比按键查找页面的第一个文档慢得多。跳过的文档越多,请求就越慢。

答案 2 :(得分:1)

这是我到目前为止所提出的 - 获取所有帖子的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

答案 3 :(得分:0)

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

    采用两个变量

  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();

                           });
  });

  }