【问题标题】:Creating a pagination index in CouchDB?在 CouchDB 中创建分页索引?
【发布时间】:2011-04-08 12:10:23
【问题描述】:

我正在尝试在 CouchDB 中创建一个分页索引视图,其中列出了找到的每个第 N 个文档的 doc._id。

我编写了以下映射函数,但 pageIndex 变量不能可靠地从 1 开始 - 事实上它似乎根据发出的值或索引长度(例如 50、55 , 10, 25 - 都以不同的文件开头,尽管我似乎得到了正确的文件数量)。

function(doc) {
  if (doc.type == 'log') {
    if (!pageIndex || pageIndex > 50) {
      pageIndex = 1;
      emit(doc.timestamp, null);
    }
    pageIndex++;
  }
}

我在这里做错了什么? CouchDB 专家将如何构建此视图?

请注意,我不想使用 mentioned elsewhere 的“startkey + count + 1”方法,因为我希望能够跳转到特定页面或最后一页(用户期望和所有),我想要一个友好的“?page=5”URI 而不是“?startkey=348ca1829328edefe3c5b38b3a1f36d1e988084b”,如果我能提供帮助,我宁愿 CouchDB 完成这项工作,而不是扩大我的应用程序。

谢谢!

【问题讨论】:

    标签: pagination couchdb mapreduce


    【解决方案1】:

    视图函数(mapreduce)纯粹是功能性的。不支持设置全局变量等副作用。 (当您将应用程序移至BigCouch 时,具有任意数据子集的多个独立服务器如何知道pageIndex 是什么?)

    因此,答案必须涉及传统的map 函数,可能以时间戳为键。

    function(doc) {
      if (doc.type == 'log') {
        emit(doc.timestamp, null);
      }
    }
    

    如何获取每 50 个文档?最简单的方法是添加skip=0skip=50skip=100 参数。然而,这并不理想(见下文)。

    一种预取每 50 个文档的确切 ID 的方法是 _list 函数,它仅每 50 行输出一次。 (实际上,您可以使用 Mustache.JS 或其他模板库来构建 HTML。)

    function() {
      var ddoc = this,
          pageIndex = 0,
          row;
    
      send("[");
      while(row = getRow()) {
        if(pageIndex % 50 == 0) {
          send(JSON.stringify(row));
        }
        pageIndex += 1;
      }
      send("]");
    }
    

    这适用于许多情况,但并不完美。以下是我正在考虑的一些注意事项 - 不一定是阻碍因素,但这取决于您的具体情况。

    不鼓励使用漂亮的 URL 是有原因的。如果我加载第 1 页,然后在前 50 个中插入一堆文档,然后单击到第 2 页,这意味着什么?如果数据变化很大,就没有完美的用户体验,用户必须以某种方式感受到数据的变化。

    skip 参数和示例_list 函数有同样的问题:它们不能缩放。使用skip,您仍然从头开始触摸视图中的每一行:在数据库文件中找到它,从磁盘读取它,然后一遍又一遍地逐行忽略它,直到您达到skip 值。对于非常方便的小值,但由于您将页面分组为 50 个组,我不得不想象您将有数千行或更多行。由于数据库大部分时间都在旋转,这可能会使页面浏览量变慢。

    _list 示例也有类似的问题,但是您预先加载所有工作,从头到尾运行整个视图,并且(可能)将相关文档 ID 发送给客户端,以便它可以快速跳转页面。但是有数十万个文档(你称它们为“日志”,所以我假设你会有很多),这将是一个非常慢的查询,没有缓存。

    总之,对于小型数据集,您可以使用page=1page=2 表单,但是随着数据集变大,您会遇到问题。随着 BigCouch 的发布,CouchDB 更适合日志存储和分析,因此(如果您正在这样做)您肯定会考虑扩展多高。

    【讨论】:

    • 很好的答案,谢谢!我认为获取所有 doc._ids 的缓存索引(如在您的第一个 map 函数中)并基本上使应用程序完成繁重的工作(并可能将其写回缓存文档)的可扩展性低于您的 _list 方法?
    • 缓存文档是合理的。也许它可能有一个时间戳值,所以你知道它什么时候太旧了。您也可以自己获取和构建该缓存文档(即不要求用户创建文档,他们只阅读它)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-15
    • 2016-06-07
    • 2012-02-19
    • 1970-01-01
    • 2010-09-23
    • 2015-01-06
    • 1970-01-01
    相关资源
    最近更新 更多