Sorting 按值排序CouchDB视图
我正在测试CouchDB,看看它如何处理记录一些搜索结果。我想做的是生成一个视图,在这个视图中,我可以根据结果生成顶部查询。目前我有这样的想法: 示例文档部分Sorting 按值排序CouchDB视图,sorting,couchdb,Sorting,Couchdb,我正在测试CouchDB,看看它如何处理记录一些搜索结果。我想做的是生成一个视图,在这个视图中,我可以根据结果生成顶部查询。目前我有这样的想法: 示例文档部分 { "query": "+dangerous +dogs", "hits": "123" } function (key, values, rereduce) { return sum(values); } 地图功能 (不完全是我需要/想要的,但足以进行测试) 减少功能 { "query": "+dangerous +
{
"query": "+dangerous +dogs",
"hits": "123"
}
function (key, values, rereduce) {
return sum(values);
}
地图功能
(不完全是我需要/想要的,但足以进行测试)
减少功能
{
"query": "+dangerous +dogs",
"hits": "123"
}
function (key, values, rereduce) {
return sum(values);
}
现在,这将得到一种格式的结果,其中查询项是键,右边是该项的计数,这很好。但我希望按值排序,而不是按键。从它的声音,这是不可能与CouchDB
那么,有没有人知道如何获得一个视图,其中我有一个有序版本的查询术语及其相关计数?我是CouchDB的新手,我想不起如何编写所需的函数。我不确定返回结果中的1,但我肯定这应该可以做到:
emit([doc.hits,split[i]],1)代码>
在文档中定义了。这在CouchDB用户邮件列表上,主要开发人员之一Chris Anderson写道:
这是一个常见的请求,但CouchDB的
视图——为此,您需要将组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…
});
此示例在中运行并使用,但它可以轻松地适应在浏览器或其他JavaScript环境中运行。当然,这个概念可以移植到任何编程语言/环境中
嗯 确实没有绝对简单的答案。然而,有几种模式
。我个人不喜欢这样,因为他们承认这是一个脆弱的解决方案,代码看起来并不轻松
Avi的答案是,在应用程序的内存中进行排序
似乎每个人最终都发现自己需要它
我喜欢的是克里斯在阿维的引用中所说的话。放松。在CouchDB中,数据库是轻量级的,能够为您提供数据的独特视角。这些天来,热门话题都是关于过滤复制的,过滤复制就是将数据的子集切分出来放到一个单独的数据库中
不管怎样,基础很简单。您从视图输出中获取.rows
,然后将其插入单独的数据库中,该数据库只需发出键入计数的命令。另一个技巧是编写一个非常简单的\u list
函数。列出将原始沙发输出“渲染”为不同格式。您的\u列表
函数应该输出
{ "docs":
[ {..view row1...},
{..view row2...},
{..etc...}
]
}
这样做的目的是按照\u bulk\u docs
API的要求对视图输出进行格式化。现在,您可以将卷曲管直接插入另一个卷曲:
curl host:5984/db/_design/myapp/_list/bulkdocs_formatter/query_popularity \
| curl -X POST host:5984/popularity_sorter/_design/myapp/_view/by_count
事实上,如果您的列表函数可以处理所有文档,您可以让它自己对它们进行排序,然后将它们返回给排序后的客户端
根据Avi的回答,我提出了这个Couchdb列表函数,它满足了我的需要,它只是一个最流行事件的报告(key=event name,value=attenders)
ddoc.lists.eventPopularity=函数(请求、恢复){
开始({标题:{“内容类型”:“文本/普通”}});
var数据=[]
while(row=getRow()){
数据推送(row);
}
数据排序(函数(a,b){
返回a.value-b.value;
}).reverse();
对于(数据中的i){
发送(数据[i].value+':'+data[i].key+“\n”);
}
}
以下是相应的视图函数供参考:
ddoc.views.eventPopularity = {
map : function(doc) {
if(doc.type == 'user') {
for(i in doc.events) {
emit(doc.events[i].event_name, 1);
}
}
},
reduce : '_count'
}
ddoc.views.eventPopularity={
地图:功能(doc){
如果(doc.type==“用户”){
对于(文档事件中的i){
发出(doc.events[i].事件名称,1);
}
}
},
减少:“\u计数”
}
以及列表函数的输出(已剪切):
165:设计驱动的创新:设计师如何促进对话
165:你的客户是人群还是社区?
164:社交媒体神话破坏者
163:不要害怕创造力!任何事情都有可能发生
159:机构需要像软件公司一样思考吗?
158:客户体验:未来趋势和见解
156:意外作家:对每个人来说都是很棒的网络拷贝
155:为什么一切都令人惊奇,但没有人快乐
我认为上面的每个解决方案都会破坏couchdb的性能。我对这个数据库很陌生。据我所知,couchdb视图在被查询之前准备结果。似乎我们需要手动准备结果。例如,每个搜索词将驻留在具有命中计数的数据库中。当有人搜索时,它的搜索词将被查找并增加命中率。当我们想看到搜索词的流行程度时,它会发出(命中率,搜索词)对 检索\u顶部\u N \u标记的链接似乎已断开,但我找到了另一种解决方案
引用编写该解决方案的开发人员的话:
与在映射步骤中返回由标记键入的结果不同,我将发射每个标记的每个匹配项。然后在reduce步骤中,我将使用散列计算按标记分组的聚合值,将其转换为数组,对其进行排序,然后选择前3个
如评论中所述,唯一的问题是长尾的情况:
问题是你必须小心你获得的标签数量;如果结果大于500字节,您将有couchdb抱怨它,因为“reduce必须有效地reduce”。不过,3个、6个甚至20个标签都不成问题
这对我来说非常有效,请查看链接以查看代码 这是一个老问题,但我觉得它仍然值得一个体面的回答(我花了至少20分钟寻找正确的答案…)
我不同意这里答案中的其他建议,认为它们不令人满意。尤其是我不喜欢它
165: Design-Driven Innovation: How Designers Facilitate the Dialog
165: Are Your Customers a Crowd or a Community?
164: Social Media Mythbusters
163: Don't Be Afraid Of Creativity! Anything Can Happen
159: Do Agencies Need to Think Like Software Companies?
158: Customer Experience: Future Trends & Insights
156: The Accidental Writer: Great Web Copy for Everyone
155: Why Everything is Amazing But Nobody is Happy
emit([doc.address.country,doc.address.state, doc.address.city], doc);
startkey=["US"]&endkey=["US",{}]
startkey=["US",{}]&endkey=["US"]