Map-Reduce 例子

在本页面

mongo shell 中,db.collection.mapReduce()方法是MapReduce命令周围的 wrapper。以下示例使用db.collection.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_idorders集合执行 map-reduce 操作到 group,并为每个cust_id计算price的总和:

  • 将 map function 定义为 process 每个输入文档:

  • 在 function 中,this指的是 map-reduce 操作正在处理的文档。

  • function maps 为每个文档的cust_id并发出cust_idprice对。

var mapFunction1 = function() {
                       emit(this.cust_id, this.price);
                   };
  • 使用两个 arguments keyCustIdvaluesPrices定义相应的 reduce function:

  • valuesPrices是一个 array,其元素是 map function 发出的price值,并按keyCustId分组。

  • function 将valuesPrice array 缩减为其元素的总和。

var reduceFunction1 = function(keyCustId, valuesPrices) {
                          return Array.sum(valuesPrices);
                      };
  • 使用mapFunction1 map function 和reduceFunction1 reduce function 对orders集合中的所有文档执行 map-reduce。
db.orders.mapReduce(
                     mapFunction1,
                     reduceFunction1,
                     { out: "map_reduce_example" }
                   )

此操作将结果输出到名为map_reduce_example的集合。如果map_reduce_example集合已存在,则操作将使用此 map-reduce 操作的结果替换内容:

使用 Item 的平均数量计算 Order 和总数量

在此 example 中,您将对orders集合执行 map-reduce 操作,以处理ord_date value 大于01/01/2012的所有文档。操作按item.sku字段分组,并计算每个sku的订单数量和订购总数量。该操作通过计算每个sku value 的每个 order 的平均数量来结束:

  • 将 map function 定义为 process 每个输入文档:

  • 在 function 中,this指的是 map-reduce 操作正在处理的文档。

  • 对于每个 item,function 将sku与一个新的 object value相关联,该 object value包含countcount和_ite用于 order 并发出skuvalue对。

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);
                       }
                    };
  • 使用两个 arguments keySKUcountObjVals定义相应的 reduce function:

  • countObjVals是一个 array,其元素是映射到 map function 传递给 reducer function 的分组keySKU值的 objects。

  • function 将countObjVals array 缩减为包含countqty字段的单个 object reducedValue

  • reducedVal中,count字段包含来自各个 array 元素的count字段的总和,qty字段包含来自各个 array 元素的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;
                  };
  • 使用两个 arguments keyreducedVal定义 finalize function。 function 修改reducedVal object 以添加名为avg的计算字段并返回修改后的 object:
var finalizeFunction2 = function (key, reducedVal) {

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

                       return reducedVal;

                    };
  • 使用mapFunction2reduceFunction2finalizeFunction2函数对orders集合执行 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。如果map_reduce_example集合已存在,则操作将现有内容与此 map-reduce 操作的结果合并。