MongoDB MapReduce返回意外结果并分组两次
我正在使用MongoDB,并希望统计集合中每个不同的“连接的_句柄”(类型为string的字段)的出现次数 我还必须根据出现的次数进行排序,所以我决定使用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};
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;
因此,每次调用都使用计数,直到上一次调用为止
我不确定我是否正确地解释了这一点,但这里有很好的文档记录(在更多的技术解释下):