20

所以我是 mongodb 和 mapreduce 的新手,遇到了这个“怪癖”(或者至少在我看来是一个怪癖)

假设我的收藏中有这样的对象:

{'键':5,'值':5}

{'键':5,'值':4}

{'键':5,'值':1}

{'键':4,'值':6}

{'键':4,'值':4}

{'键':3,'值':0}

我的地图函数只是发出键和值

我的reduce函数只是简单地添加值并且在返回它们之前添加1(我这样做是为了检查reduce函数是否被调用)

我的结果如下:

{'_id':3,'值':0 }

{'_id':4,'值':11.0}

{'_id':5,'值':11.0}

正如您所看到的,对于键 4 和 5,我得到了 11 的预期答案,但是对于键 3(集合中只有一个带有该键的条目)我得到了意想不到的 0!

这是 mapreduce 的自然行为吗?对于 MongoDB?对于 pymongo(我正在使用)?

4

5 回答 5

39

reduce 函数将具有相同键的文档合并为一个文档。如果 map 函数为特定键发出单个文档(如键 3 的情况),则不会调用 reduce 函数。

于 2012-06-13T19:32:43.683 回答
5

我意识到这是一个较老的问题,但我来到它并觉得我仍然不明白为什么会存在这种行为以及如何构建 map/reduce 功能,所以这不是问题。

如果只有一个键实例,MongoDB 不调用 reduce 函数的原因是因为它不是必需的(我希望这稍后会更有意义)。以下是reduce函数的要求

  • reduce 函数必须返回一个对象,其类型必须map 函数发出的值的类型相同。
  • valuesArray 中元素的顺序不应影响 reduce 函数的输出
  • reduce 函数必须是幂等的。

第一个要求非常重要,似乎很多人都忽略了它,因为我看到很多人在 reduce 函数中映射,然后在 finalize 函数中处理单键情况。然而,这是解决问题的错误方法。

可以这样想:如果键只有一个实例,一个简单的优化就是完全跳过 reducer(没有什么可以减少的)。单键值仍然包含在输出中,但 reducer 的目的是构建集合中多键文档的聚合结果。如果 mapper 和 reducer 输出相同的类型,那么通过查看map/reduce 函数的输出的对象结构,您应该完全没有意识到这一点。您不必使用 finalize 函数来更正未通过 reducer 运行的对象的结构。

简而言之,在您的 map 函数中进行映射,并将多键值减少为一个单一的聚合结果。

于 2014-02-28T12:46:27.803 回答
3

解决方案:

  • 在地图中添加了新字段:单:0
  • 减少将此字段更改为:单:1
  • finalize中检查该字段并进行必要的操作

    $map = new MongoCode("function() {
        var value = {
            time: this.time,
            email_id: this.email_id,
            single: 0
        };
    
        emit(this.email, value);
    }");
    
    $reduce = new MongoCode("function(k, vals) {
    
        // make some need actions here
        return {
            time: vals[0].time,
            email_id: vals[0].email_id,
            single: 1
        };
    }");
    
    $finalize = new MongoCode("function(key, reducedVal) {
        if (reducedVal.single == 0) {
            reducedVal.time = 11111;
        }
        return reducedVal;
    };");
    
于 2015-04-24T11:31:43.517 回答
1

“MongoDB 不会为只有一个值的键调用 reduce 函数。值参数是一个数组,其元素是“映射”到键的值对象。”

http://docs.mongodb.org/manual/reference/command/mapReduce/#mapreduce-reduce-cmd

于 2014-01-29T20:00:33.520 回答
0

这是 mapreduce 的自然行为吗?

是的。

于 2012-06-13T19:44:13.390 回答