我在MongoDB中使用MapReduce,我想我已经把所有这些都包围了,除了一件我还不明白的事情:reduce
运行了多少次?
例如,我有一个“项目”集合,每个项目都有一个“类别”。这是测试数据(用javascript编写,用于node.js单元测试):
var i = 0;
var dummyCategories = [
{ categoryId:(++i), categoryName:'Category '+i }, // [0] 1
{ categoryId:(++i), categoryName:'Category '+i }, // [1] 2
{ categoryId:(++i), categoryName:'Category '+i }, // [2] 3
{ categoryId:(++i), categoryName:'Category '+i }, // [3] 4
{ categoryId:(++i), categoryName:'Category '+i } // [4] 5
];
i=0;
var dummyItems = [
{ itemId: 'TestItem' + (++i), title: 'Test Item ' + i, // [0] 1
category: dummyCategories[0]
},
{ itemId: 'TestItem' + (++i), title: 'Test Item ' + i, // [1] 2
category: dummyCategories[1]
},
{ itemId: 'TestItem' + (++i), title: 'Test Item ' + i, // [2] 3
category: dummyCategories[2]
},
{ itemId: 'TestItem' + (++i), title: 'Test Item ' + i, // [3] 4
category: dummyCategories[3]
},
{ itemId: 'TestItem' + (++i), title: 'Test Item ' + i, // [4] 5
category: dummyCategories[4]
},
{ itemId: 'TestItem' + (++i), title: 'Test Item ' + i, // [5] 6
category: dummyCategories[0]
}
];
共有6个项目,5个类别,其中一个类别出现两次,其余一次出现。
在我的map
函数中,我正在发出(this.category.categoryId, { items: 1 });
。 (除了项目之外,其完整版本还包括值对象中的其他度量标准,但这种行为无论如何都是相同的。)
我的reduce
函数如下所示:
function reduce(key, values) {
var totals = {
items: 0
};
for (var i = 0; i < values.length; i++) {
totals.items += values[i].items;
}
return totals;
};
(输出结构在map中与reduce中的相同,因为它需要。)
所以我用verbose=true
通过mapReduce运行它,它显示了这些统计信息:
计数:{输出:5,发出:6,减少:1,输入:6}
输入:6有意义,有6个文件。 emit:6有意义,每个文档发出1个类别。 输出:5有意义,有5个类别。 但为什么减少只运行一次?
现在写出来,对于每次出现不止一次的每个发出的密钥,似乎都在运行reduce。因此,当一个键仅发出一次时,它不会减少它。那是对的吗?确定减少运行次数的数学公式是什么?
谢谢!
答案 0 :(得分:4)
是的,你是正确的,如果只发出一次密钥,则不会运行reduce。我不认为存在能够告诉你减少多少次运行的数学公式。
答案 1 :(得分:1)
只要有必要。对于大数据集,单个reduce调用将在节点之间拆分并同时运行。单个减少作业块的大小将根据配置而有所不同 - 文档说单个发布不能超过 最大文档大小的一半,所以我认为这意味着最大减少批量将是最大文档大小。