Map-Reduce Example

第二次修改这篇文章了,添加了我个人的一些理解,所有附加内容均会以红色、加粗表示

Map-Reduce 例子

在mongo数据库命令行中,db.collection,mapReduce()方法被封装成 mapReduce() 命令。接下来的例子会展示该方法。

接下来将在orders集合中使用下列数据来演示map-reduce操作

{
     _id: ObjectId("50a8240b927d5d8b5891743c"),
     cust_id: "abc123",
     ord_date: new Date("Oct 04, 2012"),
     status: 'A',
     price: 25,
     items: [ { sku: "mmm", qty: 5, price: 2.5 },
              { sku: "nnn", qty: 5, price: 2.5 } ]
}

返回每位顾客的消费总金额

其实就是根据 cust_id 分组,再来计算 price 的总和,如果下面的译文部分看不懂没关系,我在下面会有详细的解释的

使用map-reduce操作将orders集合按照 cust_id 分组,以及计算每个 cust_id 分组的 price 总和

1 定义 map 函数来操作该集合中的每个的文档:

。在此函数中,this代表map-reduce正在处理的文档 

。此函数将筛选出每个文档的price、cust_id字段,并将此两个字段一起输出 使用 emit 表示输出的字段,这里可以看出就是将原字段中的 cust_id 和 price 字段输出

var mapFunction1 = function() {
                       emit(this.cust_id, this.price);
                   };

2 定义对应的reduce函数,此函数有两个输入参数 keyCustId 和 valuesPrices:

。valuesPrices 是一个数组,此数组的内容是map函数中的产生的数据经过 keyCustId 分组产生的

。此函数通将通过求各 valuePrices 数组的和的形式来减少 valuesPrices 中内容的数量

var reduceFunction1 = function(keyCustId, valuesPrices) {
                          return Array.sum(valuesPrices);
                      };
3 使用代表 map 的 mapFunctionl 函数,以及代表 reduce 的 reduceFunctionl 函数来构建 map-reduce,处理 orders 中的集合

db.orders.mapReduce(
                     mapFunction1,
                     reduceFunction1,
                     { out: "map_reduce_example" }
                   )
该命令的操作结果会在当前数据库中产生一个名曰 map_reduce_example 的集合。如果该集合早已存在数据库中,此命令产生的数据会替换掉旧数据。

这里对上面的内容做一个我的解释,先看下面的图片


是不是看着很专业偷笑教科书配图般的存在啊,不耍嘴皮子了。

先看1,表示将当前文本字段中的cust_id、price字段筛选出来,这里注意!cust_id字段接下来是作为分组字段使用的,看下图:


接着传入的 price 就按照 cust_id 进行分组,以数组的形式存储,看上面的[500,250],而且cust_id和price的存储形式是

{cust_id:price},也就是2表示的形式

接着来看3,在reduce函数中,传入的两个参数就是键名,将2的形式拆成3的形式,也就是如下形式了

第一个文档传入 reduce 函数时

{keyCustId:"A123",valuesPrices:[500,250]}

第二个文档传入时

{keyCustId:'B212',valuesPrices:200}

接着在reduce函数中处理完成后,会产生一个返回值,那个返回值就是最终结果value字段的值

来看4,4的_id、value,键名都是固定的,不同的是后面的返回数据,_id 表示分组的依据,也就是 map 函数的第一个参数的值,value的值就是reduce函数的返回值,所以最开始那组数据的最终结果应该是

{_id:'abc123',value:25}

最终结果不会显示出来的,需要查看当前数据库下有一个新建的集合 map_reduce_example,使用find函数查看里面的命令就可以了,下面会展示最后的结果

顺便说一句,Array.sum( Array )是一个求数组中数据和的一个函数

统计订单以及计算每笔订单的总数

在此例子中,你将会在 orders 集合中使用 map-reduce 操作拥有 ord_date 字段,且 ord)date 字段的值大于 01/01/2012 的所有文档。此操作将文档按照 item.sku 字段分组,以及计算订单的数量,统计每个 sku 的数量。此操作通过统计每笔订单的平均值来计算 sku 的值。

1 定义map函数来操作该集合中的每个文档

。在此函数中,this 代表当前操作的文档本身

。对于 item 中的每个记录,此函数使用新定义的变量 value 对象使之与 sku 联系起来,value 对象中包含 count :1 以及 qty 等于文档中的qty 的字段,最终输出key和    value字段

var mapFunction2 = function() {
                       for (var idx = 0; idx < this.items.length; idx++) {
                           var key = this.items[idx].sku;
                           var value = {
                                         count: 1,
                                         qty: this.items[idx].qty
                                       };
                           emit(key, value);
                       }
                    };
2 定义对应的 reduce 函数,此函数拥有两个参数 keySKU 和 countObjVals:

。countObjVals 是一个数组,数组中的内容是经过 map 函数筛选出来的数据经过 keySKU 分组后产生的

。reduce 函数将 countObjVals 数组中的内容缩减后存储在对象 reducedVal 中,此对象中含有 count 和 qty 字段

。在对象 reducedVal 中,count 字段是countObjVals 数组中 count 字段的总和,qty 字段是 coutObjVals 数组中 qty 字段的总和

var reduceFunction2 = function(keySKU, countObjVals) {
                     reducedVal = { count: 0, qty: 0 };

                     for (var idx = 0; idx < countObjVals.length; idx++) {
                         reducedVal.count += countObjVals[idx].count;
                         reducedVal.qty += countObjVals[idx].qty;
                     }

                     return reducedVal;
                  };
3 定义一个 finalize 函数,此函数包含两个参数,key 和 reduceVal。此函数通过添加一个 avg 字段到 reducedVal 对象中后返回 reducedVal 字段。

var finalizeFunction2 = function (key, reducedVal) {

                       reducedVal.avg = reducedVal.qty/reducedVal.count;

                       return reducedVal;

                    };
4 在 orders 集合中,使用 mapFunctions、reduceFunctions 以及 finalizeFunction2 函数来组成 map-reduce

db.orders.mapReduce( mapFunction2,
                     reduceFunction2,
                     {
                       out: { merge: "map_reduce_example" },
                       query: { ord_date:
                                  { $gt: new Date('01/01/2012') }
                              },
                       finalize: finalizeFunction2
                     }
                   )
此操作使用 query 字段来选择 ord_date 字段的值大于 new Date ('01/01/2012') 的文档。输出结果是一个名为 map_reduce_example的集合,如果数据库中存在该集合, 新的集合中的内容会被添加到旧集合中。

为了便于理解,我直接按照上面图片的格式,把每次函数执行前后的数据写出来,便于大家理解:


再来附一张最终结果的图


---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

到上面为止就翻译完了,第一次翻译,还需要多多努力奋斗,接下来是一张上面操作的一张图片,也是mongo官网上来的















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值