当前我们会对一些大量的访问日志、交易记录等存储到Mongodb中(也可以以其它方式存放),以便进行统计分析,这里举例来说明Mongodb的MapReduce功能(和Hadoop的MapReduce原理相似)。
先看一张图:
如上图所示:orders订单字段有:客户id(cust_id)、数量(amount)、状态(status),mapReduce的map处理过程:对状态为A的记录以cust_id为key做映射,按照键分组,产生键值列表(如:将cust_id为A123的2条记录合并为一个map,key=A123,值为500和250两个值);reduce处理过程:将列表中的值化简成一个单值(如:将cust_id为A123中的两个值累加为750,_id为cust_id)。总的结果就是一个cust_id对应一个总数量值。
经过上面的分析后,我们再来解一道题,实战:
题:对商品入库记录汇总(如年中盘点),求每个商品入库笔数,总的入库数量?
goodsAmount结构:
key:商品id,value:入库数量
运行以下整段语句:
//测试数据,插入入库的商品信息
db.goodsAmount.insert({"a":1,"b":2,"c":3});
db.goodsAmount.insert({"a":1,"b":2,"c":3});
map = function() {
for(var key in this) {
emit(key, {count : 1, value : this[key]});
}
};
reduce = function(key, emits) {
totalCount = 0;
totalValue = 0;
for(var i in emits) {
totalCount += emits[i].count;
if(key != "_id") {
totalValue += emits[i].value;
}
}
return {"totalCount": totalCount, "totalValue": totalValue};
};
mr = db.runCommand({"mapreduce": "goodsAmount", "map": map, "reduce": reduce, "out":"goodsAmount_result"});
db[mr.result].find();
执行结果:
{
"result" : "goodsAmount_result", //结果集合名
"timeMillis" : 3, //运行时长,单位毫秒
"counts" : {//调试信息
"input" : 2,//发送到map函数的文档数量
"emit" : 8,//emit被调用次数,key为_id也做了2次调用,其它key做了6次调用
"reduce" : 4,//合并结果次数
"output" : 4//结果文档数量
},
"ok" : 1
}
{ "_id" : "_id", "value" : { "totalCount" : 2, "totalValue" : 0 } }
{ "_id" : "a", "value" : { "totalCount" : 2, "totalValue" : 2 } }
{ "_id" : "b", "value" : { "totalCount" : 2, "totalValue" : 4 } }
{ "_id" : "c", "value" : { "totalCount" : 2, "totalValue" : 6 } }