Map-Reduce Examples

在本页面

mongo shell 中,db.collection.mapReduce()方法是mapReduce命令的包装。以下示例使用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 } ]
}

返回每个 Client 的总价

orders集合执行 map-reduce 操作以对cust_id进行分组,并为每个cust_id计算price的总和:

  • 定义 Map 功能来处理每个 Importing 文档:

  • 在函数中,this表示正在执行 map-reduce 操作的文档。

  • 该函数将每个文档的priceMap 到cust_id并发出cust_idprice对。

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

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

  • 该函数将valuesPrice数组减少为其元素的总和。

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

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

计算订单和总数量以及每件商品的平均数量

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

  • 定义 Map 功能来处理每个 Importing 文档:

  • 在函数中,this表示正在执行 map-reduce 操作的文档。

  • 对于每个项目,该函数将sku与新对象value关联,该对象包含1count和订单的项目qty并发出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);
                       }
                    };
  • 使用两个参数keySKUcountObjVals定义相应的 reduce 函数:

  • countObjVals是一个数组,其元素是 Map 到由 map 函数传递给 reducer 函数的分组的keySKU值的对象。

  • 该函数将countObjVals数组简化为包含countqty字段的单个对象reducedValue

  • reducedVal中,count字段包含单个数组元素中count字段的总和,qty字段包含单个数组元素中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;
                  };
  • 用两个参数keyreducedVal定义一个 finalize 函数。该函数修改reducedVal对象以添加一个名为avg的计算字段,并返回修改后的对象:
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 操作的结果合并。