MongoDB MapReduce-发出一个键/一个值不调用reduce

MongoDB MapReduce-发出一个键/一个值不调用reduce,mongodb,mapreduce,pymongo,Mongodb,Mapreduce,Pymongo,所以我对mongodb和mapreduce基本上是新手,遇到了这个“怪癖”(或者至少在我看来是怪癖) 假设我的收藏中有这样的对象: {'key':5,'value':5} {‘键’:5,‘值’:4} {‘键’:5,‘值’:1} {‘键’:4,‘值’:6} {'key':4,'value':4} {“键”:3,“值”:0} Mymap函数只发出键和值 我的reduce函数只是简单地将值相加,然后返回它们加1(我这样做是为了检查reduce函数是否被调用) 我的结果如下: {u id':3,'val

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

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

{'key':5,'value':5}

{‘键’:5,‘值’:4}

{‘键’:5,‘值’:1}

{‘键’:4,‘值’:6}

{'key':4,'value':4}

{“键”:3,“值”:0}

Mymap函数只发出键和值

我的reduce函数只是简单地将值相加然后返回它们加1(我这样做是为了检查reduce函数是否被调用)

我的结果如下:

{u id':3,'value':0}

{“u id”:4,“value”:11.0}

{“u id”:5,“value”:11.0}

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


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

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

这是mapreduce的自然行为吗

是。

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


我意识到这是一个比较老的问题,但我发现我仍然不明白为什么会出现这种行为,以及如何构建map/reduce功能,这样就不成问题了

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

  • reduce函数必须返回一个对象,该对象的类型必须与map函数发出的值的类型相同
  • valuesArray中元素的顺序不应影响reduce函数的输出
  • reduce函数必须是幂等函数
第一个需求非常重要,似乎很多人忽视了它,因为我看到很多人在reduce函数中映射,然后在finalize函数中处理单键情况。然而,这是解决这个问题的错误方法

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

简而言之,在映射函数中进行映射,并在reduce函数中将多个键值缩减为单个聚合结果。

解决方案:

  • 在地图中添加了新字段:单个:0
  • 减少中将此字段更改为:单个:1
  • 完成中检查此字段并执行所需操作

    $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;
    };");
    

需要明确的是,这是map reduce的设计方法。如果您想修改具有唯一密钥的文档(如密钥3),请考虑使用终结函数:如果要在结果中包含单个文档的键,那么解决方案是什么??@ RaviKhakhkhar,单个文档仍然包含在结果中,只是还原函数从未被调用过,谢谢!你救了我的命:)@Jenna,你说这就是map reduce的设计方法。你有没有任何参考资料来解释这种设计理念?没有-这对于“一般先生”来说是不自然的。无论是最初的MR论文,还是Hadoop Map Reduce都没有做到这一点。您可能希望将“1”转换为减速器中的另一种类型,对吗?因此,一般来说,跳过减速器将是一个非常糟糕/奇怪的想法;-)这并不意味着mongo的MR不这样做——但这不是“一般预期的行为”。这里mongo说retuce必须返回与map相同类型的值。然而,我同意这是不好的,古怪的,出乎意料的和不清楚的。