MongoDB 聚合操作之 MapReduce 使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_18948359/article/details/88777216

MongoDB Map Reduce

前面介绍了一些 MongoDB 的聚合操作,这里介绍下 MapReduce 的相关内容。

Map-Reduce 是一种计算模型,简单的说就是将大批量的工作(数据)分解(MAP)执行,然后再将结果合并成最终结果(REDUCE)。

MongoDB 提供的 Map-Reduce 非常灵活,对于大规模数据分析也相当实用。

Map-Reduce 的解释

Map: 指的是将数据取出。

Reduce: 负责数据的最后统计操作。

MapReduce 命令语法

官方地址:https://docs.mongodb.com/manual/reference/method/db.collection.mapReduce

// 语法
>db.collection.mapReduce(
   function() {emit(key,value);},  //map 函数
   function(key,values) {return reduceFunction},   //reduce 函数
   {
      out: collection,
      query: document,
      sort: document,
      limit: number
   }
)

参数说明

  • map:映射函数 (生成键值对序列,作为 reduce 函数参数)。
  • reduce:统计函数,reduce 函数的任务就是将 key-values 变成 key-value,也就是把 values 数组变成一个单一的值 value。
  • out : 统计结果存放集合 (不指定则使用临时集合,在客户端断开后自动删除)。
  • query: 一个筛选条件,只有满足条件的文档才会调用map函数。(query。limit,sort可以随意组合)
  • sort: 和 limit 结合的 sort 排序参数(也是在发往map函数前给文档排序),可以优化分组机制
  • limit:发往 map 函数的文档数量的上限(要是没有limit,单独使用sort的用处不大)

使用 MapReduce 要实现两个函数 Map 函数和 Reduce 函数,Map 函数调用 emit(key, value), 遍历 collection 中所有的记录, 将 key 与 value 传递给 Reduce 函数进行处理。

Map 函数必须调用 emit(key, value) 返回键值对。

下面是来自官网的截图(介绍执行的过程):

扫描二维码关注公众号,回复: 5793799 查看本文章

实战

首先准备一点数据

db.getCollection('sales').insertMany([
{ "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-03-01T08:00:00Z") },
{ "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "date" : ISODate("2014-03-01T09:00:00Z") },
{ "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-03-15T09:00:00Z") },
{ "_id" : 4, "item" : "xyz", "price" : 5, "quantity" : 20, "date" : ISODate("2014-04-04T11:21:39.736Z") },
{ "_id" : 5, "item" : "abc", "price" : 10, "quantity" : 10, "date" : ISODate("2014-04-04T21:23:13.331Z") }
]);

示例:按照 item 分组,统计出每个 item 下面的 price 合计

// 创建出 map 方法
var mapFun = function(){
    // 按照 job 分组,取出 price 字段
    emit(this.item, this.price);
};

// 创建 reduce 方法
var reduceFun = function(key, values){
    return Array.sum(values)
};

// 执行 mapReduce
db.sales.mapReduce(
    mapFun,
    reduceFun,
    {
        out : "sales_1"    //  out 指的是将数据放入 sales_1 这个集合中
    }
);

// 返回结果
{
        "result" : "sales_1",
        "timeMillis" : 439,
        "counts" : {
                "input" : 5,
                "emit" : 5,
                "reduce" : 2,
                "output" : 3
        },
        "ok" : 1
}

创建两个函数,并且查询数据:

返回结果参数说明

  • result:储存结果的 collection 的名字,这是个临时集合,MapReduce 的连接关闭后自动就被删除了。
  • timeMillis:执行花费的时间,毫秒为单位
  • counts:
    • input:满足条件被发送到map函数的文档个数
    • emit:在map函数中emit被调用的次数,也就是所有集合中的数据总量
    • ouput:结果集合中的文档个数(count对调试非常有帮助)
  • ok:是否成功,成功为1

查询返回结果值

db.sales_1.find();

// 在 map 方法中传入多个字段时的处理方式
var mapFun = function(){
     emit(this.item, { "price" : this.price, "quantity" : this.quantity });
}

var reduceFun = function(key, values){
    var sumPrice = 0, quantity = 0;
    // 循环取出传入的内容
    for (var key in values){
        // 对数据进行合计
        sumPrice += values[key].price;
        quantity += values[key].quantity;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_18948359/article/details/88777216