英文原文地址:https://docs.mongodb.com/v3.2/tutorial/map-reduce-examples/。
本文章属个人翻译,作个人学习之用,如有雷同,纯属巧合。如有错误之处,欢迎指正。
Map-Reduce示例
mongo
shell中,db.collection.mapReduc()
方法是对命令mapReduce
的封装。以下例子使用db.collection.mapReduce()
方法。
考虑以下对集合order
的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 } ]
}
返回每个客户的总价格
对orders
集合执行map-reduce操作,按cust_id
分组,计算每个cust_id
的price
的总和:
定义map函数来处理每个输入文档:
- 在函数中
this
引用的是map-reduce操作处理中的文档。 - 该函数对每个文档把
price
映射到cust_id
,然后产生cust_id与price
对。
var mapFunction1 = function() { emit(this.cust_id, this.price); };
- 在函数中
定义相应的reduce函数,有连个参数,keyCustId和valuesPrices:
- valuesPrice是一个数组,其元素是由map函数按keyCustId分组的price值。
- 该函数对valuesPrice数据归约成其元素之和。
var reduceFunction1 = function(keyCustId, valuesPrices) { return Array.sum(valuesPrices); };
对
orders
集合中的所有文档执行map-reduce操作,用mapFunction1
作为map函数,reduceFunction1
作为reduce函数。db.orders.mapReduce( mapFunction1, reduceFunction1, { out: "map_reduce_example" } )
该操作把结果输出到名为
map_reduce_example
的集合。如果该集合已经存在,该操作会用map-reduce的结果替换掉该集合的内容。计算每个商品的订单和总数量、平均数量
该例子中,你将对
orders
集合中ord_date
值大于01/01/2012的所有文档进行map-reduce操作。该操作对item.sku
字段分组,计算每个sku
的订单数和订单总量。该操作最后计算每个`sku的平均订单数量。定义处理每个输入文档的map函数:
- 在函数中
this
引用的是map-reduce操作处理中的文档。 - 对于每个商品,该函数用一个新的对象
value
来关联sku
,该对象的count
是1,qty
是订单的商品数量,并且输出sku-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); } };
- 在函数中
定义相应的reduce函数,它有两个参数,keySKU和countObjVals:
- countObjVals是一个数组,它的元素被映射到分组的keySKU,是通过map函数传过来的。
- 该函数把countObjVals归约到单个reducedValue对象,该对象包含count和qty字段。
- 在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; };
定义一个终止函数,有两个参数,key和reducedVal。该函数修改reducedVal对象,添加了一个叫做avg的计算字段,并且返回修改后的对象。
var finalizeFunction2 = function (key, reducedVal) { reducedVal.avg = reducedVal.qty/reducedVal.count; return reducedVal; };
用
mapFunction2
,reduceFunction2
和finalizeFunction2
函数对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的结果与已经存在的内容合并。