我试图在Mongo中使用mapReduce来计算给定值出现次数的计数次数。
这是我的map函数,我测试以确保每个值都是一个字符串:
function mapFunction () {
function normalizeDate(date) {
var day = date.getDay(),
month = date.getMonth(),
year = date.getYear();
return new Date(year, month, day);
}
if (this.events.event.toString() === "[object Object]"
|| typeof(this.events.event) !== 'string') {
throw new Error("Not a string...");
}
emit(normalizeDate(this.date), this.events.event);
}
为了完整起见,这是我的reduce函数:
function reduceFunction (date, event_arry) {
return event_arry.reduce(function (a, b) {
if (a[b]) {
a[b]++;
}
else {
a[b] = 1;
}
return a;
}, {});
}
然后,我在mongo repl中运行mapReduce:
mongos> db.events.mapReduce(mapFunction, reduceFunction, {out: 'mr_test'})
{
"result" : "mr_test",
"timeMillis" : 148,
"counts" : {
"input" : 3481,
"emit" : 3481,
"reduce" : 82,
"output" : 14
},
"ok" : 1,
}
并且没有错误,表明所有event
都属于string
类型。
然而,当我查看mr_test
集合中的输出时,我得到了几个这样的条目:
mongos> db.mr_test.find()
{ "_id" : ISODate("0113-04-05T00:00:00Z"), "value" : { "[object Object]" : 4 } }
{ "_id" : ISODate("0113-04-06T00:00:00Z"), "value" : { "[object Object]" : 5 } }
{ "_id" : ISODate("0113-04-30T00:00:00Z"), "value" : { "[object Object]" : 1, "eventTypeA" : 9, "eventTypeB" : 14, "eventTypeC" : 19 } }
对此有一个很好的解释吗?如果是这样,它是什么?
答案 0 :(得分:2)
对此有一个很好的解释(与MongoDB mapreduce的所有问题中99%相同。你的地图值与你的reduce返回的格式不同。
您的reduce函数必须返回与map函数相同的格式。
你正在发出一个字符串,你希望得到一份文件!您需要做的是在map函数中发出您最终期望的确切格式:
emit(normalizeDate(this.date), {this.events.event:1} );
这说:“对于特定的一天(密钥),我正在跟踪单个事件字符串,其总数为1”。
然后调整reduce函数迭代值数组并将它合并在一起,记住,因为reduce函数可以被多次调用(为特定键重新减少结果)你正在“合并”或减少的文档可以是单个{date:number}或具有多个{date1:number,date2:number,...}的复杂文档