MapReduce有两种写法,也可以说mongodb所有的命令行都有两种写法。
但突然间发现MapReduce不同的写法会有不同的结果,接下来我们一起来看:
第一种:直接使用扩展属性。
1)emit函数的第2参数直接使用数值。
> db.entities.mapReduce(function(){emit(this.age,1)},function(key,value){var tot al=0;for(var i in value){total+=value[i];} return total;},{query:{age:{"$gt":97} },out:{inline:1}}) { "results" : [ { "_id" : 98, "value" : 10602 }, { "_id" : 99, "value" : 11533 } ], "timeMillis" : 414, "counts" : { "input" : 22135, "emit" : 22135, "reduce" : 223, "output" : 2 }, "ok" : 1, }
看到results.value是正常值,方法可行。
2)emit函数的第2参数使用object对象。
> db.entities.mapReduce(function(){emit(this.age,{count:1})},function(key,value) {var total=0;for(var i in value){total+=value[i].count;} return total;},{query:{ age:{"$gt":97}},out:{inline:1}}) { "results" : [ { "_id" : 98, "value" : NaN }, { "_id" : 99, "value" : NaN } ], "timeMillis" : 643, "counts" : { "input" : 22135, "emit" : 22135, "reduce" : 223, "output" : 2 }, "ok" : 1, }
看到results.value是Nan,证明此方法不可行。
第二种方法:使用内置命令函数runCommand。
1)emit函数的第2参数直接使用数值。
> db.runCommand({mapReduce:"entities",map:function(){emit(this.age,1)},reduce:fu nction(key,value){var total=0;for(var i in value){total+=value[i];} return {coun t:total,key:key};},query:{age:{$gt:97}},out:{inline:1}}) { "results" : [ { "_id" : 98, "value" : { "count" : "0[object Object]11", "key" : 98 } }, { "_id" : 99, "value" : { "count" : "0[object Object]111111111111111111111 11111111111111", "key" : 99 } } ], "timeMillis" : 383, "counts" : { "input" : 22135, "emit" : 22135, "reduce" : 223, "output" : 2 }, "ok" : 1 }
看到results.value是竟然是这样的,证明此方法不可行。
2)emit函数的第2参数使用object对象。
> db.runCommand({mapReduce:"entities",map:function(){emit(this.age,{count:1})},r educe:function(key,value){var total=0;for(var i in value){total+=value[i].count; } return {count:total,key:key};},query:{age:{$gt:98}},out:{inline:1}}) { "results" : [ { "_id" : 99, "value" : { "count" : 11533, "key" : 99 } } ], "timeMillis" : 388, "counts" : { "input" : 11533, "emit" : 11533, "reduce" : 116, "output" : 1 }, "ok" : 1 }
看到results.value是正常值,方法可行。
为什么会这样?原因以后再补上。
结论:
1、使用扩展函数db.xx.mapreduce时,emit函数的第2参数必须是使用数值。
2,使用内置命令函数db.runCommand时,emit函数的第2参数必须object对象。程序内部运行就是使用此方法。