介绍 Map-Reduce是一种计算模型,简单的说就是将大批量的工作(数据)分解(MAP)执行,然后再将结果合并成最终结果(REDUCE)。 MongoDB提供的Map-Reduce非常灵活,可以高效的进行大规模数据的统计分析。
语法 格式一 1 2 3 4 5 6 7 8 9 10 11 12 13 db.collection .mapReduce ( function ( ) {emit (key,value)}, function (key,values ) {return reduced}, <collection> ) { finalize : function (key, reduced ){return finalized} out : <collection>|{inline :true }, query : <document >, sort : <document >, limit : <number>, }
格式二 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 db.runCommand ({ mapReduce : <collection>, map : <function >, reduce : <function >, finalize : <function >, out : <output>, query : <document >, sort : <document >, limit : <number>, scope : <document >, jsMode : <boolean>, verbose : <boolean>, bypassDocumentValidation : <boolean>, collation : <document > })
示例 示例集合person
存储各省市居民的姓名、性别等记录
1 2 3 4 5 6 7 8 9 10 11 12 13 1. { "name" : "姓名1" , "gender" : "男" , "city" : "城市a" , "province" : "省份A" } 2. { "name" : "姓名2" , "gender" : "女" , "city" : "城市b" , "province" : "省份B" } 3. ..
现用mapReduce统计各省市人口性别比例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 db.person .mapReduce ( function ( ){ var key = {province :this .province , city :this .city } var value = {total : 1 } if (this .gender == '男' ){ value.male = 1 }else if (this .gender == '女' ){ value.female = 1 }else { value.unknown = 1 } emit (key, value) }, function (key, values ){ var value = {} values.forEach (function (item ){ for (var k in item){ value[k] = (value[k]||0 ) + item[k] } }) return value },{ query :{}, sort :{province :1 , city :1 }, finalize : function (key, rValue ){ for (var k in rValue){ if (k !== 'total' ){ rValue[k] = rValue[k]/rValue.total } } return rValue }, out :{inline :true }, } ).find ()
执行结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 [ { "_id" : { "province" : "省份A" , "city" : "城市a" }, "value" : { "total" : 40.0 , "male" : 0.425 , "female" : 0.575 } }, { "_id" : { "province" : "省份A" , "city" : "城市b" }, "value" : { "total" : 1.0 , "male" : 1.0 } }, { "_id" : { "province" : "省份A" , "city" : "城市c" }, "value" : { "total" : 150.0 , "male" : 0.526 , "female" : 0.473 } }, ... ]
特别说明
当key对应的value只有一组时不会触发reduce。所以,map函数emit的value值的格式最好和reduce函数return值一致,避免最终的结果不一致。
同一个key可能会触发多次reduce,即reduce接收的values中有些item元素可能是已经reduced的,累积时要考虑这种情况(即values包含直接emit的value,也包含reduce返回的value)。
reduce返回值不支持数组,若需多值请用对象格式。
按key排序可以减少reduce的次数,提高处理效率。
out可以指定输出到一个collection集合,但这样会导致写操作;指定为{inline:true}时mongodb会用runReadCommand代替runCommand——if inline output is specified, we need to apply readPreference on the command as it could be run on a secondary.