pagination - 在 CouchDB 中创建分页索引?

标签 pagination couchdb mapreduce

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

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

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

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

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

谢谢!

最佳答案

View 函数(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,您仍然从头开始接触 View 中的每一行:在数据库文件中找到它,从磁盘读取它,然后忽略它,一遍又一遍,逐行,直到您点击skip值。对于较小的值,这非常方便,但由于您将页面分组为 50 个页面,我必须想象您将有数千或更多行。这可能会导致页面浏览速度变慢,因为数据库大部分时间都在运转。

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

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

关于pagination - 在 CouchDB 中创建分页索引?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3647101/

相关文章:

couchdb - CouchDB 上的多主机配额

mongodb - 带有 MongoDB 的 MapReduce 真的非常慢(30 小时,而同等数据库在 MySQL 中为 20 分钟)

php - cakephp中多个模型的单一分页

python - 使用分页模块的 Django-Rest-Framework csv 模块

ajax - 将 HTTP 范围 header 与字节以外的范围说明符一起使用?

pagination - 如何在 django-rest-framework 中为我的自定义分页类使用 pagination_class

javascript - 使用 _conflicts 而不是 409 创建或更新

javascript - Node.js 中的 Couchdb 更新事件处理程序

java - 如何使用 Hadoop Mapreduce 将 EBCDIC 转换为 TEXT

java - Hadoop 文本比较不起作用