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

时间:2012-06-13 19:11:27

标签: mongodb mapreduce pymongo

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

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

  

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

     

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

     

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

     

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

     

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

     

{'key':3,'value':0}

我的地图功能只会发出键和值

我的 reduce 函数只是添加值 AND ,然后返回它们添加1(我这样做是为了检查是否甚至调用了reduce函数)

我的结果如下:

  

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

     

{'_ id':4,'value':11.0}

     

{'_ id':5,'value':11.0}

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

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

5 个答案:

答案 0 :(得分:37)

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

答案 1 :(得分:4)

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

如果有一个密钥实例,MongoDB不会调用reduce函数的原因是因为没有必要(我希望这会在一瞬间更有意义)。以下是requirements for reduce functions

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

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

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

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

答案 2 :(得分:3)

解决方案:

  • 地图中添加了新字段:single:0
  • 缩小将此字段更改为:single: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;
    };");
    

答案 3 :(得分:1)

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

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

答案 4 :(得分:0)

  

这通常是mapreduce的自然行为吗?