mapReduce从字面上来理解就是两个过程:map映射以及reduce化简。是一种大数据处理方法,其难度不高,从性能上来说属于比较暴力的(通过N台服务器同时来计算),但相较于group以及aggregate来说,功能更强大,并更加灵活。
-
映射过程:先把某一类数据分组归类,这里的映射过程是支持分布式的,一边遍历每一台服务器,一边进行分类。
-
化简过程:然后再在分组中进行运算,这里的化简过程也是支持分布式的,在分类的过程中直接运算了。也就是说如果是一个求和的过程,先在a服务器分组求和,然后再在b服务器分组求和····最后再把化简以后的数据进行最终处理。在映射化简的过程都是每台服务器自己的CPU在运算,大量的服务器同时来进行运算工作,这就是大数据基本理念。
mapReduce可以用js语法来写。下面是结构:
db.table.mapReduce( map, reduce, { query: query, out: out, //指定结果集以什么方式存储,可选参数包括: //replace:如果文档(table)存在,则替换table, //merge:如果文档中存在记录,则覆盖已存在的文档记录 //reduce: 如果文档中存在相同key的记录了,则先计算两条记录,然后覆盖旧记录 // {inline:1} 在内存中存储记录,不写入磁盘(用户数据量少的计算) sort: sort, limit: limit, finalize: function //这个function主要用来在存入out之前可以修改数据,function(key,values) { //return modifiedValues;} scope: document, //设置参数值,在这里设置的值在map,reduce,finalize函数中可见 jsMode:boolean //是否减少执行过程中BSON和JS的转换,默认true] //false时 BSON-->JS-->map-->BSON-->JS-->reduce-->BSON,可处理非常大的mapreduce, //true时BSON-->js-->map-->reduce-->BSON verbose:boolean //是否产生更加详细的服务器日志,默认true keytemp:boolean //true或false,表明结果输出到的collection是否是临时的,如果为true,则会在客户端连接中断后自动删除,如果你用的是MongoDB的mongo客户端连接, //那必须exit后才会删除。如果是脚本执行,脚本退出或调用close会自动删除结果collection } ) 必备参数:map,reduce, out,
详解:
map: function() {emit(this.cat_id,this.goods_number); }, // 函数内部要调用内置的emit函数,cat_id代表根据cat_id来进行分组,goods_number代表把文档中的goods_number字段映射到cat_id分组上的数据,其中this是指向向前的文档的,这里的第二个参数可以是一个对象,如果是一个对象的话,也是作为数组的元素压进数组里面;
reduce: function(cat_id,all_goods_number) {return Array.sum(all_goods_number)}, // cat_id代表着cat_id当前的这一组,all_goods_number代表当前这一组的goods_number集合,这部分返回的就是结果中的value值;
out: <output>, // 输出到某一个集合中,注意本属性来还支持如果输出的集合如果已经存在了,那是替换,合并还是继续reduce? 另外还支持输出到其他db的分片中,具体用到时查阅文档,筛选出现的键名分别是_id和value;
query: <document>, // 一个查询表达式,是先查询出来,再进行mapReduce的
sort: <document>, // 发往map函数前先给文档排序
limit: <number>, // 发往map函数的文档数量上限,该参数貌似不能用在分片模式下的mapreduce
finalize: function(key, reducedValue) {return modifiedObject; }, // 从reduce函数中接受的参数key与reducedValue,并且可以访问scope中设定的变量
scope: <document>, // 指定一个全局变量,能应用于finalize和reduce函数
jsMode: <boolean>, // 布尔值,是否减少执行过程中BSON和JS的转换,默认true,true时BSON-->js-->map-->reduce-->BSON,false时 BSON-->JS-->map-->BSON-->JS-->reduce-->BSON,可处理非常大的mapreduce。
verbose: <boolean> // 是否产生更加详细的服务器日志,默认true
在集合 orders 中查找 status:"A" 的数据,并根据 cust_id 来分组,并计算 amount 的总和。图解:
下面是我个人的动手实验。
1. 在logsInfo表数据中,根据logcategory进行分组统计数量。
2. db.表名. mapReduce实例:
3. 查看mapReduce的统计结果:
mapReduce中map函数可以理解为分组, emit里的key为分组依据,value建议用count统计次数。
下面这个例子value为数据库的值耗时慢,达不到效果。
mapReduce中的query参数,一般用来过滤使用。 当满足query的条件时,调用mapReduce。相当于SQL的where条件。 query的语句请看我上篇mongodb的文章,聚合查询中有写道这些条件操作符。