今天对Mongo的Mapreduce产生了兴趣,然后就实际操作尝试玩了一吧
MapReduce是个非常灵活和强大的数据聚合工具。它的好处是可以把一个聚合任务分解为多个小的任务,分配到多服务器上并行处理。
MongoDB中的MapReduce主要有以下几阶段:

  1. Map:把一个操作Map到集合中的每一个文档
  2. Shuffle: 根据Key分组对文档,并且为每个不同的Key生成一系列(>=1个)的值表(List of values)。
  3. Reduce: 处理值表中的元素,直到值表中只有一个元素。然后将值表返回到Shuffle过程,循环处理,直到每个Key只对应一个值表,并且此值表中只有一个元素,这就是MR的结果。
  4. Finalize:此步骤不是必须的。在得到MR最终结果后,再进行一些数据“修剪”性质的处理。MongoDB中使用emit函数向MapReduce提供Key/Value对。

Reduce函数接受两个参数:Key,emits. Key即为emit函数中的Key。 emits是一个数组,它的元素就是emit函数提供的Value。
==Reduce函数的返回结果必须要能被Map或者Reduce重复使用,所以返回结果必须与emits中元素结构一致。==上面这句话需要特别注意,由于Mongo的文档的最大嵌套数默认为100,假设当你Reduce处理的数据长度超过100时,如果你不遵循以上规则处理数据,那没结果数据会和预期产生较大偏差
Map或者Reduce函数中的this关键字,代表当前被Mapping文档。
首先生成测试数据,以便后面的操作

for (var i = 1; i <= 10000000; i++) {
    var rnd = Math.floor(Math.random()*1000);
    db.test.insert({
        x: i,
        name1: "MACLEAN" + rnd,
        name2: "MACLEAN" + rnd,
        name3: "MACLEAN" + rnd
    })
}

数据生成完成后开始执行Mapreduce进行数据分析

db.getCollection("test").mapReduce(function () {
    emit(this.name1, {row:1, sum_x: this.x});
}, function (key, values) {
    var reduced = {row: 0, sum_x:0}; 
    values.forEach(function(value){
        reduced.sum_x += value.sum_x;
        reduced.row += value.row;
    });
    return reduced;
}, {
    out: "test_out",
    sort: { },
    finalize: Code("function (key, value) {\r\n\tvalue.avg_x = value.sum_x / value.row;\n\treturn value;\n}"),
    verbose: true
});

以下是统计后test_out集合的一部分数据
MACLEAN100 { "row" : 7657, "sum_x" : 29040263567, "avg_x" : 3792642.49275173 }
MACLEAN101 { "row" : 7597, "sum_x" : 28804430079, "avg_x" : 3791553.2551007 }
MACLEAN102 { "row" : 7551, "sum_x" : 28675681911, "avg_x" : 3797600.57091776 }
MACLEAN103 { "row" : 7736, "sum_x" : 29058510559, "avg_x" : 3756270.75478283 }
MACLEAN104 { "row" : 7571, "sum_x" : 28931298340, "avg_x" : 3821331.17685907 }
MACLEAN105 { "row" : 7742, "sum_x" : 29234912055, "avg_x" : 3776144.67256523 }
MACLEAN106 { "row" : 7683, "sum_x" : 29293090728, "avg_x" : 3812715.18000781 }
MACLEAN107 { "row" : 7694, "sum_x" : 29146879923, "avg_x" : 3788260.97257603 }


吃饭饭睡觉觉
62 声望4 粉丝