在不是分布式的环境,为什么要使用mapreduce
因为mongodb的聚合查询结果不能超过16m
因为mongodb的group有20000的限制
所以只有使用mapreduce才能避免这些
-----------------------------------------------------------------------
【参考如下】
http://cn.docs.mongodb.org/manual/core/map-reduce/
http://my.oschina.net/huzorro/blog/73879?p=1#rpl_273686466
【详细解析】
文档结构如下:
Spcode
Spname
Consignid
Consname
Region
Regionname
Serviceid
Servicename
Srctermid
要实现任意字段的组合, 分组, 对Srctermid做去重操作。
Mysql:
SELECT Spcode, Spname, Consignid, Consname, COUNT(DISTINCT(Srctermid)) FROM mt_log_201208 GROUP BY Spcode, Spname, Consignid, Consname
Where Logtime<20120821 and Logtime>20120801;
mongodb的mapreduce操作
res = db.runCommand({
mapreduce:'mo_log_201208', 【查询的集合】
query:{Logtime:{$gte:'20120801', $lte:'20120821'}}, 【查询条件】
map:function() { 【处理的数据源】
emit({Spcode:this.Spcode, Spname:this.Spname,
Consignid:this.Consignid, Consname:this.Consname}, [参数一:要分组的字段]
{"data":[{"Srctermid":this.Srctermid}]}); [参数二:分组后,自定义要处理的每个组的数据数组[单个组的所有Srctermid的值[1,23,455,66...]],传给reduce的value处理的数据]
},
reduce:function(key, value) { 【处理函数:value就是map传过来的,返回的就是返回集合的值】
var ret = {data:[]};
var srctermid = {};
for(var i in value) {
var ia = value[i];
for(var j in ia.data) {
if(!srctermid[ia.data[j].Srctermid]) {
srctermid[ia.data[j].Srctermid] = true;
ret.data.push(ia.data[j]);
}
}
}
return ret;
},
finalize:function(key, values){ 【对返回值封装后,传给结果】
return {count:values.data.length};
},
out:'tmp_mo_spcode_consignid_1',
verbose:true
})
【java】
String mapfun = "function() {" +"emit(this.platCode,{count:1})}";
String reducefun = "function(key, value) {" +
"var ret = {count:0};" +
"for(var i in value) {" +
"ret.count += value[i].count;" +
"}" +
"return ret;" +
"}";
System.out.println(MongodbUtil.getHourLogPhoneCollection().mapReduce(mapfun, reducefun, "relt2", new BasicDBObject()));
【java】
String mapfun = "function() {" +"emit({chCode:this.chCode,platCode:this.platCode,optCode:this.optCode,provCode:this.provCode,retCode:this.retCode,MSISDN:this.MSISDN},{count:this.count,suc_count:this.suc_count})}";
String reducefun = "function(key, value) {" +
"var ret = {count:0,suc_count:0};" +
"for(var i in value) {" +
"ret.count += value[i].count;" +
"ret.suc_count+= value[i].suc_count;" +
"}" +
"return ret;" +
"}";
讲解:
【map】
{chCode:this.chCode,platCode:this.platCode,optCode:this.optCode,provCode:this.provCode,retCode:this.retCode,MSISDN:this.MSISDN} | 分组里面的所有字段 like: group by chCode,platCode,optCode......
{count:this.count,suc_count:this.suc_count,name:this.name} | group by后 单个组的所有组员组成的数组 name:this.name=》{'gt','zwj','xx','aa','77'}
【reduce】
value | 就是上面说的数组
function | 对数组做处理
return ret | 单个组最终要返回的内容