2

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

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

我想运行一个 map reduce 来获取每个城市有多少人的列表,所以结果将如下所示:

{
  _id: "Seattle",
  value: 10
}

我的 map reduce 函数如下所示:

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为键,然后为它找到的每个匹配城市添加一个到结果中。但是,在生成的 map reduce 中,该值相差很大。将我的 reduce 功能切换为:

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

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

为什么结果不一样?value在 reduce 函数中我不是 1 吗?

4

1 回答 1

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 函数将2在第二个 reduce 调用之后返回,因为值列表中有两个项目。在您的第二个 reduce 函数中,您正确地将这些值相加,而不是仅仅计算它们,这给出了正确的答案。

我个人认为CouchDB 文档更好地解释了为什么您需要为其值输入数组使用可交换和关联的 reduce 函数。

于 2013-07-26T09:30:28.053 回答