我正在寻找map / reduce函数来计算设计文档中的状态。 您可以在下面看到我当前数据库中的示例文档。
{
"_id": "0238f1414f2f95a47266ca43709a6591",
"_rev": "22-24a741981b4de71f33cc70c7e5744442",
"status": "retrieved image urls",
"term": "Lucas Winter",
"urls": [
{
"status": "retrieved",
"url": "http://...."
},
{
"status": "retrieved",
"url": "http://..."
}
],
"search_depth": 1,
"possible_labels": {
"gender": "male"
},
"couchrest-type": "SearchTerm"
}
我想摆脱status
密钥,而是根据网址的状态来计算它。
我当前的by_status
视图如下所示:
function(doc) {
if (doc['status']) {
emit(doc['status'], null);
}
}
我尝试了一些东西,但实际上没有任何效果。现在我的Map Function
看起来像这样:
function(doc) {
if(doc.urls){
emit(doc._id, doc.urls)
}
}
我的Reduce Function
function(key, value, rereduce){
var reduced_status = "retrieved"
for(var url in value){
if(url.status=="new"){
reduced_status = "new";
}
}
return reduced_status;
}
结果是我到处找到了绝对不正确的东西。
我试图缩小问题的范围,似乎value
不是数组,当我使用以下Reduce Function
我到处都得到长度1,这是不可能的因为我有12个文件我的数据库,每个包含20到200个URL
function(key, value, rereduce){
return value.length;
}
alt text http://img.skitch.com/20100316-qeawxgd5pru8d5i6bprygcsmhf.jpg
我做错了什么? (我知道我希望你为我编写代码并且我感到内疚,但是现在我从数据库中获取数据后我会计算ruby中的状态。很高兴已经从中获取了正确的数据。数据库)
答案 0 :(得分:3)
reduce函数的变量value
是map函数发出的值数组。在您的情况下,value
是一个由“url” - 数组组成的数组。在蒲团中运行map-reduce时,它会设置group=true
,以便map-reduce分别针对map函数发出的每个键运行。在您的情况下,这些键是文档_ids
。也就是说,reduce函数value
是一个数组,其元素都是属于某个doc _id的url-arrays。由于doc _ids是唯一的,因此最终使用reduce函数value
是一个包含一个元素的数组,此元素是相应doc的url-array。这就是为什么value.length
与reduce函数一直为1的原因。
但它可能会变得更糟:如果你最终进入rereduce循环,reduce函数的value
是一个值数组,由之前调用reduce函数返回。在您的情况下,您可以使用value
调用reduce函数,使其看起来像["retrieved","new","retrieved"]
,这不会产生正确的结果。
通常,reduce函数用于聚合map-function发出的数据,例如计算行数或总结值 - 这在您的情况下是不必要的。您可以在这里阅读有关couchdb中map-reduce的更多信息:
http://wiki.apache.org/couchdb/Introduction_to_CouchDB_views
答案 1 :(得分:1)
doc.urls
似乎是包含Object
属性和status
属性的url
数组。所以你的Reduce功能应该是
function(key, value, rereduce){
var reduced_status = "retrieved";
for(var i=0; i<value.length; i++) {
if(value[i].status=="new"){
reduced_status = "new";
}
}
return reduced_status;
}
编辑:实际上该函数应在找到status == "new"
后立即返回。
答案 2 :(得分:0)
感谢Alsciende推动我走向正确的解决方案,事实证明我真的不明白还原功能。我根本不需要减少功能。
这是我Map Function
为我解决的问题。
function(doc) {
if(doc.urls){
var reduced_status = "retrieved";
for(var i=0; i<doc.urls.length; i++) {
if(doc.urls[i].status=="new"){
reduced_status = "new";
break;
}
}
emit(reduced_status, null);
}
}