我写了一个mapreduce函数,其中的记录以下列格式发出
{userid:<xyz>, {event:adduser, count:1}}
{userid:<xyz>, {event:login, count:1}}
{userid:<xyz>, {event:login, count:1}}
{userid:<abc>, {event:adduser, count:1}}
其中userid是键,其余是该键的值。 在MapReduce函数之后,我希望得到以下格式的结果
{userid:<xyz>,{events: [{adduser:1},{login:2}], allEventCount:3}}
为了实现这一点,我编写了以下reduce函数 我知道这可以通过聚合框架和mapreduce中的分组来实现,但是我们需要针对复杂场景的类似功能。所以,我采取这种方法。
var reducefn = function(key,values){
var result = {allEventCount:0, events:[]};
values.forEach(function(value){
var notfound=true;
for(var n = 0; n < result.events.length; n++){
eventObj = result.events[n];
for(ev in eventObj){
if(ev==value.event){
result.events[n][ev] += value.allEventCount;
notfound=false;
break;
}
}
}
if(notfound==true){
var newEvent={}
newEvent[value.event]=1;
result.events.push(newEvent);
}
result.allEventCount += value.allEventCount;
});
return result;
}
运行完美,当我运行1000条记录时,当有3k或10k记录时,我得到的结果是这样的
{ "_id" : {...}, "value" :{"allEventCount" :30, "events" :[ { "undefined" : 1},
{"adduser" : 1 }, {"remove" : 3 }, {"training" : 1 }, {"adminlogin" : 1 },
{"downgrade" : 2 } ]} }
无法理解此undefined
的来源以及各个事件的总和小于allEventCount。集合中的所有文档都具有非空字段event
,因此不存在未定义的可能性。
Mongo DB版本 - 2.2.1 环境 - 本地机器,没有分片。
在reduce函数中,当类似的操作result.events[n][ev] += value.allEventCount;
通过时,为什么此操作会失败result.allEventCount += value.allEventCount;
?
johnyHK建议的纠正答案
减少功能:
var reducefn = function(key,values){
var result = {totEvents:0, event:[]};
values.forEach(function(value){
value.event.forEach(function(eventElem){
var notfound=true;
for(var n = 0; n < result.event.length; n++){
eventObj = result.event[n];
for(ev in eventObj){
for(evv in eventElem){
if(ev==evv){
result.event[n][ev] += eventElem[evv];
notfound=false;
break;
}
}}
}
if(notfound==true){
result.event.push(eventElem);
}
});
result.totEvents += value.totEvents;
});
return result;
}
答案 0 :(得分:2)
emit
函数中map
对象的形状必须与reduce
函数返回的对象相同,因为reduce
的结果可以在处理大量文档时(例如在这种情况下),反馈到reduce
。
所以你需要改变你的emit
以发出像这样的文档:
{userid:<xyz>, {events:[{adduser: 1}], allEventCount:1}}
{userid:<xyz>, {events:[{login: 1}], allEventCount:1}}
然后相应地更新reduce
功能。