[英]Map/Reduce on an array of hashes in CouchDB
我正在寻找一种映射/归约函数来计算设计文档中的状态。 在下面,您可以查看当前数据库中的示例文档。
{
"_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;
}
替代文字http://img.skitch.com/20100316-qeawxgd5pru8d5i6bprygcsmhf.jpg
我究竟做错了什么? (我知道我想让您为我编写代码,但我感到内,但是现在我从数据库中获取数据后就进行了红宝石状态的计算。如果已经从数据库中获取了正确的数据,那就太好了。数据库)
reduce函数的变量value
是map函数发出的值的数组。 在您的情况下, value
是一个由“ url”数组组成的数组。 在蒲团中运行map-reduce时,它会设置group=true
以便针对map函数发出的每个键分别运行map-reduce。 在您的情况下,这些键是文档_ids
。 也就是说,reduce函数的value
是一个数组,其元素都是属于某个doc _id的所有url数组。 由于doc _id是唯一的,因此您最终得到reduce函数的value
是一个包含一个元素的数组,该元素是相应doc的url数组。 这就是为什么value.length
函数的value.length
始终为1的原因。
但是,情况可能会变得更糟:如果您最终进入一个rereduce循环,则reduce函数的value
是先前调用reduce函数所返回的value
数组。 在您的情况下,您将使用看起来像["retrieved","new","retrieved"]
value
来调用reduce函数,这不会导致正确的结果。
通常,reduce函数用于聚合map函数发出的数据,例如对行进行计数或对值求和-在您的情况下这不是必需的。 您可以在此处阅读更多关于map-reduce的信息:
http://wiki.apache.org/couchdb/Introduction_to_CouchDB_views
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"
立即返回。
感谢Alsciende推动我寻求正确的解决方案,结果我真的不了解reduce函数。 我根本不需要reduce函数。
这是我为我解决的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);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.