Map Reduce上的Reduce函数显示错误的结果——原因



我有一个数据结构,可以跟踪不同城市的人:

//in db.persons
{
  name: "John",
  city: "Seattle
},
{
  name: "Bill",
  city: "Portland"
}

我想运行一个地图缩减来获得每个城市有多少人的列表,所以结果会是这样的:

{
  _id: "Seattle",
  value: 10
}

我的地图缩减功能如下:

map = function(){
  var city = this.city
  emit(city, 1);
};

reduce = function(key, values){
    var result = 0;
    values.forEach(function(value){
      result += 1;
    });
    return result;
}

非常简单的东西,我想它会把city作为一个键,然后为它找到的每个匹配城市的结果加一个。但是,在生成的贴图reduce上,该值被很大一个因素禁用。将我的reduce功能切换为:

reduce = function(key, values){
    var result = 0;
    values.forEach(function(value){
      result += value;
    });
    return result;
}

value添加到结果(应该是1,正如我从emit函数中理解的那样)返回了正确的结果。

为什么结果不同?在reduce函数中,我的value不是1吗?

之所以会发生这种情况,是因为MongoDB可以为同一个键多次调用reduce函数。下面是一个简单的例子:

假设您的数据库中只有三个文档,每个文档的"城市"都是"西雅图"。在发射阶段之后,你会有一组发射的物体,看起来像

{'Seattle' : 1}. {'Seattle' : 1}. {'Seattle' : 1}

在发射阶段完成之后,还原阶段开始。在最简单的情况下,reduce函数将被调用为reduce('Seattle', [1,1,1])。在这种情况下,您的第一个函数将正常工作。然而,reduce函数可能被调用多次:

reduce('Seattle', [1,1]) -> {'Seattle' : 2}, {'Seattle', 1}

reduce('Seattle', [2,1])

在这种情况下,第一个reduce函数将在第二次reduce调用后返回2,因为值列表中有两项。在第二个reduce函数中,您可以正确地将值加在一起,而不仅仅是计算它们,这会给出正确的答案。

我个人认为,CouchDB文档对这一点的解释稍微好一点,说明了为什么需要为其值数组输入交换和关联的reduce函数。

相关内容

  • 没有找到相关文章

最新更新