使用变量键在CouchDB中分页

使用变量键在CouchDB中分页,couchdb,Couchdb,这里有很多关于使用CouchDB分页的问题,但是没有一个完全符合我的想法 基本上,我有一个按投票数排序的结果集,我想按降序遍历该结果集 这是地图供参考 function(doc) { emit(doc.votes); } 现在,问题来了。我发现startkey\u docid本身不起作用。您必须将它与startkey结合使用。问题是,对于查询,我没有使用startkey参数(我不想限制结果,只想得到最大值->最小值)。我想我可以用startkey={{doc.voces}}&startke

这里有很多关于使用CouchDB分页的问题,但是没有一个完全符合我的想法

基本上,我有一个按投票数排序的结果集,我想按降序遍历该结果集

这是
地图
供参考

function(doc) {
  emit(doc.votes);
}
现在,问题来了。我发现
startkey\u docid
本身不起作用。您必须将它与
startkey
结合使用。问题是,对于查询,我没有使用
startkey
参数(我不想限制结果,只想得到最大值->最小值)。我想我可以用startkey={{doc.voces}}&startkey_docid={{doc.\u id}}来代替,但是当有人点击“下一页”链接时,文档的投票数可能已经改变了

解决这个问题的方法似乎很明显:只需设置
startkey=9999999
,它将返回数据库中的所有文档,我就可以使用
startkey\u docid
从上次停止的文档开始。奇怪的是,当我这样做时,
startkey\u docid
停止工作,只允许再次返回所有结果。显然,
startkey
需要与
startkey\u docid
中使用其
\u id
的文档上的密钥完全相等

我想问的是,当实际的
startkey
可能在您想要使用它的时候发生了变化时,是否有人知道使用
startkey\u docid
页面的解决方法?我的应用程序是否应该通过
\u id
查找文档,并立即使用
doc.vows
值,希望它在请求之间的几毫秒内没有改变?即使这样也不太可靠


编辑:最后切换到Mongo的速度,所以这个问题有点没有意义。

我从来没有做过这样的事情,但我想我知道怎么做。你所能做的就是拍下评级的快照,并在每一页中参考它。您可能希望视图不占用太多空间,因此不应映射在快照后投票未更改的文档的单独副本。因此,您可以执行以下操作:

  • 在文档中添加一些带有时间戳的评级历史记录
  • 像这样绘制收视率和历史
  • 在应用程序中获取当前时间:
    start\u time=Date.now()
    并查询所有页面
  • 清理比最旧的活动会话更早的历史记录
  • 问题是,如果您发出
    [投票,日期]
    并尝试分页,您将永远不知道要获取每页所需数量的文档。总有一些旧版本需要跳过,并且必须从DB中生成下一个get。这就是为什么你可以考虑发布:<代码> [日期,投票] < /C>,读取视图总是两次-对于<代码> StistyTime< /Cuff>和当前时间,并对结果进行合并和排序(类似于归并排序)。

    广告1:

    广告2:

    广告3:

    合并列表,在应用程序中按投票进行排序(在列表功能中打开)。 如果您在使用
    start\u docid
    时遇到问题,那么您可以发出
    [日期、投票、id]
    并显式使用id进行查询。即使此特定文档更改了其
    投票
    ,它仍将在历史记录中可用

    广告4: 如果您发出
    [日期,投票]
    ,则只需获取过时的历史记录宽度:
    ?开始键=[0]&结束键=[最早的\u活动会话\u时间]&包含\u结束=假
    ,并使用以下内容更新它们:

    注意:我还没有测试过它,所以如果没有修改,它预计不会运行:)

    据我所知,CouchDB使用b树阴影进行更新,原则上应该可以访问视图的旧版本。我不喜欢CouchDB设计,所以这只是一个猜测,似乎没有任何(文档化的)API用于此。

    我现在无法找到任何简单的解决方案,但有以下选项:

    • 不要经常将您的排序列表复制到小型专用数据库中,这样它将比stale=ok更陈旧
    • 修改您的模式,使您能够按一些更稳定的数据进行排序。查看CouchDb指南中的银行/分类账示例:。试着记录每一次投票,比如每小时减少一次。作为奖励,您将获得历史/趋势:)

    我有点惊讶这个问题没有得到回答,因为CouchDB Futon的功能基本上是在你通过map函数的结果分页时实现的。我打开firebug,查看在分页时javascript控制台中发生了什么,并看到对于每一组分页结果,它都在传递startkey和startkey_docid。因此,尽管问题是如何在不包含startkey的情况下分页,但CouchDB指定startkey是必需的,并演示了它如何工作。未指定endkey,因此如果指定的startkey只有一个结果,则下一组分页结果还将包含与startkey不匹配的排序结果的下一个键

    因此,要澄清一点,这个问题的答案是,在分页和跟踪startkey_docid时,还需要捕获同一文档的startkey,这将是下一组结果的开始。调用分页结果时,按照couchdb的要求使用捕获的startkey和startkey_docid。禁用endkey,这样结果将继续到排序结果的下一个键

    希望能够在不指定键的情况下分页的用例场景有点奇怪。假设下一个分页结果的start docid确实将其键值从9大幅更改为3。我们还假设map结果中只存在一个docid实例,即使它可能出现多次(我认为这就是为什么需要指定startkey)。作为用户
    { ...,
      votes: 12,
      history: [
        {date: 1357390271342, votes: 10},
        {date: 1357390294682, votes: 11}
      ]
    }
    
    function (doc) {
      emit([{}, doc.votes], null);
      doc.history && doc.history.forEach(function(h) {
        emit([h.date, h.votes], null);
      });
    }
    
    ?startkey=[start_time, votes]&limit=items_per_page_plus1
    ?startkey=[{}, votes]&limit=items_per_page_plus1
    
    function(doc, req) {
      if (!doc || !doc.history) return [null, 'Error'];
      var history = new Array();
      var oldest = +(req.query.date);
      doc.history.forEach(function(h) {
        if (h.date >= oldest)
          history.push(h);
      });
      doc.history = history;
      return [doc, 'OK'];
    }