Map -reduce 就是先把数据拆分然后合并的的一种思想,在map 方法中至少要调用一次内置函数emit,该函数需要两个参数,第一个是参数key,可以理解为关系数据库中的group by 的字段,第二个参数是value,也就是要进行聚合操作的字段。emit 的作用是根据key ,把value组合为一个数组,为reduce提供输入参数值。执行reduce 处理,需要用两个参数,第一个参数是key 第二个参数是value数组,也就是上一步中产生的结果。在这个函数里进行聚合处理,并返回处理后的对象,对上一步的结果进行finalize处理。把结果输出到out指定的目标(v1.7 以上版本可以指定out{inline :1}直接返回结果集)例如:
db.users.mapReduce(m, r, {out : {inline : 1}})
MongoDB中使用emit函数向MapReduce提供Key/Value对。Reduce函数接受两个参数:Key,emits. Key即为emit函数中的Key。 emits是一个数组,它的元素就是emit函数提供的Value。Reduce函数的返回结果必须要能被Map或者Reduce重复使用,所以返回结果必须与emits中元素结构一致。Map或者Reduce函数中的this关键字,代表当前被Mapping文档。
map = %Q{
function(){
emit({userinfo_id:this.userinfo_id,customer_id:this.customer_id},{paycost:this.paycost})
}
}
reduce = %Q{
function(key,values){
var res={order_count:0,order_amount:0.0}
values.forEach(function(val){
res.order_count += 1;
if(!isNaN(val.paycost) && val.paycost!=""){
res.order_amount = res.order_amount +parseFloat(val.paycost);
}
});
return res;
}
}
results = OrderStateChange.where({'customer_id'=>analyse_infos[:customer_id],'userinfo_id'=>analyse_infos[:userinfo_id],'state'=>{'$in' => ['receive','completed']}}).map_reduce(map, reduce).out(inline: true)
这种操作最终将会按照我们设定的方式返回的信息{_id:{userinfo_id:“121212”,customer_id:“23322”},value:{paycost:30}}
map中的参数的其实就是为reduce 提供(key ,value),key 和value都是可以封装多个参数的如emit({userinfo_id:this.userinfo_id,customer_id:this.customer_id},{paycost:this.paycost})
这个emit中的key 就是{userinfo_id:this.userinfo_id,customer_id:this.customer_id},value就是{paycost:this.paycost}。mongodb 中MR的使用可以非常大的提升数据的查询和统计速度。真是屡试不爽