按值排序CouchDB视图

Lee*_*ald 37 sorting couchdb

我正在测试CouchDB以了解它如何处理记录一些搜索结果.我想做的是生成一个视图,我可以从结果中生成最顶层的查询.目前我有这样的事情:

示例文档部分

{
  "query": "+dangerous +dogs",
  "hits": "123"
}
Run Code Online (Sandbox Code Playgroud)

地图功能 (不完全是我需要/想要但它足以进行测试)

function(doc) {
  if (doc.query) {
    var split = doc.query.split(" ");
    for (var i in split) {
      emit(split[i], 1);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

减少功能

function (key, values, rereduce) {
  return sum(values);
}
Run Code Online (Sandbox Code Playgroud)

现在,这将使我得到一个格式,其中查询术语是关键,右边是该术语的计数,这很好.但我希望它按价值排序,而不是钥匙.从它的声音来看,CouchDB还不能实现这一点.

那么,有没有人有任何想法,我如何获得一个视图,我有一个查询条款及其相关计数的有序版本?我对CouchDB很新,我想不出我是如何编写所需的函数的.

Jas*_*ith 24

确实没有简单的答案.但是有几种模式.

  1. http://wiki.apache.org/couchdb/View_Snippets#Retrieve_the_top_N_tags.我个人并不喜欢这样,因为他们承认这是一个脆弱的解决方案,代码并不是放松的.

  2. Avi的答案,就是在您的应用程序中对内存进行排序.

  3. 看起来每个人都发现自己最终需要的couchdb-lucene!

  4. 我喜欢的是克里斯在Avi的报价中所说的话.放松.在CouchDB中,数据库是轻量级的,并且擅长为您提供独特的数据视角.目前,关于过滤复制的嗡嗡声都是关于将数据的子集切片放入单独的数据库中.

    无论如何,基础很简单.您.rows从视图输出中取出,然后将其插入到一个单独的数据库中,该数据库只是键入计数键.另一个技巧是编写一个非常简单的_list函数.列表将原始沙发输出"渲染"为不同的格式.你的_list功能应该输出

    { "docs":
        [ {..view row1...},
          {..view row2...},
          {..etc...}
        ]
    }
    
    Run Code Online (Sandbox Code Playgroud)

    这样做的方法是完全按照_bulk_docsAPI的要求格式化视图输出.现在你可以直接将卷曲管道卷成另一个卷曲:

    curl host:5984/db/_design/myapp/_list/bulkdocs_formatter/query_popularity \
     | curl -X POST host:5984/popularity_sorter/_design/myapp/_view/by_count
    
    Run Code Online (Sandbox Code Playgroud)
  5. 实际上,如果您的列表函数可以处理所有文档,您可以让它自己对它们进行排序并将它们返回到已排序的客户端.

  • 别客气.如果不清楚我会说第一选择=在客户端排序; 第二选择=使用另一种观点(两者都是AVI更简洁地确定的!) (2认同)
  • 我很佩服这种努力,但这几乎是一个转折点.我能有什么回报 ? (2认同)

Avi*_*lax 13

出现在CouchDB用户邮件列表中,主要开发人员之一Chris Anderson写道:

这是一个常见的请求,但CouchDB的视图不直接支持 - 为此,您需要将group-reduce查询复制到另一个数据库,并构建一个视图以按值排序.

这是我们在动态范围查询和增量索​​引方面做出的权衡.

我最近也需要这样做,最后我在我的应用程序层中做了这件事.这在JavaScript中很容易做到:

db.view('mydesigndoc', 'myview', {'group':true}, function(err, data) {

    if (err) throw new Error(JSON.stringify(err));

    data.rows.sort(function(a, b) {
        return a.value - b.value;
    });

    data.rows.reverse(); // optional, depending on your needs

    // do something with the data…
});
Run Code Online (Sandbox Code Playgroud)

此示例在Node.js中运行并使用node-couchdb,但它可以很容易地适应在浏览器或其他JavaScript环境中运行.当然,这个概念可以移植到任何编程语言/环境中.

HTH!

  • 只需将sort函数更改为`return b.value - a.value`就可以避免`data.rows.reverse()` (4认同)

roy*_*650 6

这是一个老问题,但我觉得它仍然值得一个体面的答案(我花了至少 20 分钟寻找正确的答案......)

我不同意这里答案中的其他建议,并觉得它们不令人满意。特别是我不喜欢对应用层中的行进行排序的建议,因为它不能很好地扩展并且不能处理需要限制数据库中结果集的情况。

这个线程中建议了我遇到的更好的方法,它假定如果您需要对查询中的值进行排序,您应该将它们添加到键集中,然后使用范围查询键 - 指定所需的键并放松值范围。例如,如果您的密钥由国家、州和城市组成:

emit([doc.address.country,doc.address.state, doc.address.city], doc);
Run Code Online (Sandbox Code Playgroud)

然后您只查询国家/地区并免费对其余关键组件进行排序:

startkey=["US"]&endkey=["US",{}] 
Run Code Online (Sandbox Code Playgroud)

如果您还需要颠倒顺序 - 请注意,简单的定义是descending: true不够的。您实际上需要颠倒开始和结束键顺序,即:

startkey=["US",{}]&endkey=["US"]
Run Code Online (Sandbox Code Playgroud)

请参阅此重要来源的更多参考。