MongoDB MapReduce返回意外结果并分组两次

MongoDB MapReduce返回意外结果并分组两次,mongodb,mapreduce,grouping,Mongodb,Mapreduce,Grouping,我正在使用MongoDB,并希望统计集合中每个不同的“连接的_句柄”(类型为string的字段)的出现次数 我还必须根据出现的次数进行排序,所以我决定使用mapreduce,一切都很顺利,但突然我开始得到意想不到的结果,我没有更改任何代码 这是我的地图: function() { emit(this.concatenated_handles, { count: 1}); } 这是减少: r = function(key, values) { var result = {count : 0};

我正在使用MongoDB,并希望统计集合中每个不同的“连接的_句柄”(类型为string的字段)的出现次数

我还必须根据出现的次数进行排序,所以我决定使用mapreduce,一切都很顺利,但突然我开始得到意想不到的结果,我没有更改任何代码

这是我的地图:

function() { emit(this.concatenated_handles, { count: 1}); }
这是减少:

r = function(key, values) { var result = {count : 0}; values.forEach(function(value) { result.count++; }); return result; }
r = function(key, values) { var result = {count : 0}; values.forEach(function(value) { result.count++; }); return result; }
它为某些字段返回正确的值,而为其他字段返回不正确的值。我记录了输出,现在就是了(只显示被窃听的字段)

此字段在其他几行之后再次开始分组(所有重新分组都在末尾)

以上所有字段都将在末尾重新分组。它们看起来是一样的,但它们分组了两次,因此产生了意想不到的结果。但并非所有记录都是这样

我哪里做错了?组字段是一个字符串


谢谢

好的,MongoDB可以递归或部分调用MapReduce。因此,reduce函数应该是幂等的

您可能会说我的reduce函数也是幂等元,因为值映射的结构是发射的,而reduce返回的值的结构是相同的。然而,需要注意的一个非常重要的点是——每当以迭代方式进行调用时,第一次调用的结果将作为输入传递给第二次调用

因此,在我的例子中,减少:

r = function(key, values) { var result = {count : 0}; values.forEach(function(value) { result.count++; }); return result; }
r = function(key, values) { var result = {count : 0}; values.forEach(function(value) { result.count++; }); return result; }
对同一个键的每个后续调用都将以0开始递增,并添加1,而不是添加上一次迭代传递给它的计数value.count

因此,与其这样做

result.count++; 
我应该做的

result.count += value.count;
因此,每次调用都使用计数,直到上一次调用为止

我不确定我是否正确地解释了这一点,但这里有很好的文档记录(在更多的技术解释下):