我尝试在我的集合中使用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
函数返回的键一样?
原因是因为这是mapReduce的工作原理。从文档点:
MongoDB可以对同一个键多次调用reduce函数。在这种情况下,先前reduce函数对该键的输出将成为下一次调用该键的reduce函数的输入值之一。
和后面的点:
返回对象的类型必须与map函数发出的值的类型相同,以确保以下操作为真:
因此,即使您没有像文档所指出的那样"更改签名",您仍然只在一个减少通道中一次处理n
项,然后在下一个通道中处理另一个n
项。在最终的处理过程中,一个片段中返回的数组与另一个片段中的数组组合在一起。
所以发生的事情是你的reduce返回一个数组,但它不是"所有"的项目你发出的关键,只是其中的一些。然后在同一个"键"上的另一个reduce处理更多的项目。最后,这两个数组(或可能更多)再次发送给reduce,以尝试按预期实际"reduce"这些项。
这是一般的概念,所以当你只是向后推数组时,你得到的结果也就不足为奇了。
简而言之,mapReduce在块中处理输出的"键",而不是一次全部处理。最好现在就知道,免得以后成为问题。