在MongoDB中可以使用MapReduce进行一些复杂的聚合查询


Map函数和Reduce函数可以使用JavaScript来实现


可以通过db.runCommand或mapReduce命令来执行一个MapReduce的操作:



折叠复制代码




  1. db.runCommand(

  2. { mapreduce : <collection>,

  3. map : <mapfunction>,

  4. reduce : <reducefunction>

  5. [, query : <queryfilter object>]

  6. [, sort : <sortthe query. useful for optimization>]

  7. [, limit : <numberof objects to return from collection>]

  8. [, out : <output-collectionname>]

  9. [, keeptemp: <true|false>]

  10. [, finalize : <finalizefunction>]

  11. [, scope : <objectwhere fields go into javascript global scope>]

  12. [, verbose : true]

  13. }

  14. );

  15. #或者使用一个包装后的Helper命令

  16. db.collection.mapReduce(mapfunction,reducefunction[,options]);




如果没有定义out,则它执行后默认生成一个临时的collection,当client连接断开后,该collection会自动被清除


一个简单的列子,有一个user_addr的collection,结果如下:



折叠复制代码




  1. db.user_addr.find({'Uid':'test@sohu.com'})

  2. { "_id" : ObjectId("4bbde0bf600ac3c3cc7245e3"), "Uid" : "yangsong@sohu.com", "Al" : [

  3. {

  4. "Nn" : "test-1",

  5. "Em" : "test-1@sohu.com",

  6. },

  7. {

  8. "Nn" : "test-2",

  9. "Em" : "test-2@sohu.com",

  10. },

  11. {

  12. "Nn" : "test-3",

  13. "Em" : "test-3@sohu.com",

  14. }

  15. ] }




存储了一个用户(Uid)对应的联系人信息(Al),现在要查询每个Em联系人对应的数目,则建立如下的MapReduce



折叠复制代码




  1. m=function() {

  2. for (index in this.Al) {

  3. emit(this.Al[index].Em, 1);

  4. }

  5. }

  6. r=function(k, vals) {

  7. var sum=0;

  8. for (index in vals) {

  9. sum += vals[index];

  10. > }

  11. return sum;

  12. }

  13. res=db.user_addr.mapReduce(m,r)

  14. {

  15. "result" : "tmp.mr.mapreduce_1272267853_1",

  16. "timeMillis" : 29,

  17. "counts" : {

  18. "input" : 5,

  19. "emit" : 26,

  20. "output" : 26

  21. },

  22. "ok" : 1,

  23. }

  24. db[res.result].find()




MongoDB中的group函数实际上也需要借助MapReduce来实现


如:按照uid来group,计算出每个uid有多少个联系人



折叠复制代码




  1. r=function (obj,prev) {  

  2.     prev.sum += obj.Al.length;  

  3. }  

  4. db.user_addr.group({key:{'Uid':1},reduce:r,initial:{sum:0}})