介绍 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.