我尝试将mapReduce用于我的收藏。仅用于调试我返回vals
值作为第二个参数传递reduce
函数,如下所示:
db.runCommand({
"mapreduce":"MyCollection",
"map":function() {
emit( {
country_code:this.cc,
partner:this.di,
registeredPeriod:Math.floor((this.ca - 1399240800)/604800)
},
{
count:Math.ceil((this.lla - this.ca)/86400)
});
},
"reduce":function(k, vals) {
return {
'count':vals
};
},
"query":{
"ca":{
"$gte":1399240800
},
"di":405,
"cc":"1"
},
"out":{
"inline":true
}
});
我得到了这样的结果:
{
"results" : [
{
"_id" : {
"country_code" : "1",
"distribution" : 405,
"installationPeriod" : 0
},
"value" : {
"count" : [
{
"count" : 37
},
{
"count" : 38
}
]
}
},
{
"_id" : {
"country_code" : "1",
"distribution" : 405,
"installationPeriod" : 1
},
"value" : {
"count" : 36
}
},
{
"_id" : {
"country_code" : "1",
"distribution" : 405,
"installationPeriod" : 4
},
"value" : {
"count" : [
{
"count" : [
{
"count" : 16
},
{
"count" : 16
}
]
},
{
"count" : 15
}
]
}
}
],
"timeMillis" : 38,
"counts" : {
"input" : 130,
"emit" : 130,
"reduce" : 5,
"output" : 6
},
"ok" : 1
}
我真的不知道为什么我将多维数组作为reduce
函数的第二个参数。我的意思是这部分结果:
{
"_id" : {
"country_code" : "1",
"distribution" : 405,
"installationPeriod" : 4
},
"value" : {
"count" : [
{
"count" : [ // <= Why is this multidimensional?
{
"count" : 16
}
为什么这是多维的?为什么嵌入式数组的键与reduce
函数返回的相同?
答案 0 :(得分:1)
原因是因为这是mapReduce的工作原理。来自documentation point:
MongoDB可以为同一个密钥多次调用reduce函数。在这种情况下,该键的reduce函数的先前输出将成为该键的下一个reduce函数调用的输入值之一。
稍后一点:
返回对象的类型必须与map函数发出的值的类型相同,以确保以下操作为真:
因此,即使您没有像文档所指出的那样“更改签名”,您仍然只在一个reduce pass中一次处理n
项,然后在下一个pass中再处理n
个项目。在最终处理时会发生什么,一个片段中返回的数组与另一个片段中的数组合并。
所以发生了什么是你的reduce返回一个数组,但它不是你为密钥发出的“全部”项目,只是其中一些。然后另一个减少相同的“关键”处理更多的项目。最后,这两个数组(或可能更多)再次被发送到reduce,以试图实际“减少”这些项目。
这是一般概念,因此当您只是推回阵列时,这就不足为奇了。
简短版本,mapReduce处理块中的输出“键”而不是一次性处理。现在,在它成为你之前的问题之前,最好先了解它。