我正在尝试在 mongo shell 中的 mongodb 上运行 map reduce。出于某种原因,在减少阶段,我收到了对同一个键的多次调用(而不是单个键),所以我得到了错误的结果。 我不是这个领域的专家,所以也许我犯了一些愚蠢的错误。任何帮助表示赞赏。
谢谢。
这是我的小例子:
我正在创建 10000 个文档:
var i = 0;
db.docs.drop();
while (i < 10000) {
db.docs.insert({text:"line " + i,index:i});
i++;
}
然后我基于模块 10 做 map-reduce(所以我除了在每个“桶”中获得 1000 个)
db.docs.mapReduce(
function() {
emit(this.index%10,1);
},
function(key,values) {
return values.length;
},
{
out : {inline : 1}
}
);
但是,我得到以下结果:
{
"results" : [
{
"_id" : 0,
"value" : 21
},
{
"_id" : 1,
"value" : 21
},
{
"_id" : 2,
"value" : 21
},
{
"_id" : 3,
"value" : 21
},
{
"_id" : 4,
"value" : 21
},
{
"_id" : 5,
"value" : 21
},
{
"_id" : 6,
"value" : 21
},
{
"_id" : 7,
"value" : 21
},
{
"_id" : 8,
"value" : 21
},
{
"_id" : 9,
"value" : 21
}
],
"timeMillis" : 76,
"counts" : {
"input" : 10000,
"emit" : 10000,
"reduce" : 500,
"output" : 10
},
"ok" : 1,
}
最佳答案
Map/Reduce 本质上是一种递归操作。特别是 documented requirements for the reduce
function包括以下语句:
MongoDB can invoke the
reduce
function more than once for the same key. In this case, the previous output from thereduce
function for that key will become one of the input values to the nextreduce
function invocation for that key.
因此,您必须期望输入仅仅是由先前调用计算的数字。以下代码通过实际添加值来做到这一点:
db.docs.mapReduce(
function() { emit(this.index % 10, 1); },
function(key,values) { return Array.sum(values); },
{ out : {inline : 1} } );
现在,emit(key, 1)
在某种程度上更有意义,因为 1
不再只是用于填充数组的任何数字,而是它的值被考虑。
作为旁注,请注意这是多么危险:对于较小的数据集,可能会意外给出正确的结果,因为引擎认为不需要并行化。
关于mongodb - 在 mongodb map-reduce 中使用相同的键多次调用 reduce,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19252830/