MongoDB数据分析之MapReduce

来源:互联网 发布:登录到mysql服务器端 编辑:程序博客网 时间:2024/05/16 19:44

1.关于数据类型:如果是使用控制台插入的数据,你插入的数字,很可能存成了Double,而想存成整型,则必须要用NumberInt()、NumberLong()                         来,参考网址:http://www.cnblogs.com/lekko/p/3240028.html


2.MapReduce映射化简操作图:


    参考网址:http://wrox.cn/article/100035881/


3.MapReduce官网格式

     db.runCommand(  
 { mapreduce : <collection>,  
   map : <mapfunction>,  
   reduce : <reducefunction>,  
   out : <see output options below>  
   [, query : <query filter object>]  
   [, sort : <sorts the input objects using this key. Useful for optimization, like sorting by the emit key for fewer reduces>]  
   [, limit : <number of objects to return from collection, not supported with sharding>]  
   [, keeptemp: <true|false>]  
   [, finalize : <finalizefunction>]  
   [, scope : <object where fields go into javascript global scope >]  
   [, jsMode : true]  
   [, verbose : true]  
 }  
);  

参数说明:

mapreduce:要操作的目标集合

map:映射函数(生成键值对序列,作为Reduce函数的参数) 

reduce:统计函数

query:目标记录过滤

sort:对目标记录排序

limit:限制目标记录数量

out:统计结果存放集合(如果不指定则使用临时集合,在客户端断开后自动删除)

keeptemp:是否保留临时集合

finalize:最终处理函数(对reduce返回结果执行最终整理后存入结果集合)

scope:向map、reduce、finalize导入外部变量

verbose:显示详细的时间统计信息

4.例子:对runoob数据库中class集合进行分组,统计各个班级的学生人数(或年龄大于22的人数)

  应用场景:对students集合中的数据进行统计,根据classid显示每个班级的学生数量。初始数据如下:

Shell代码  收藏代码
  1. > db.students.find()  
  2. "_id" : ObjectId("5031143350f2481577ea81e5"), "classid" : 1"age" : 20"name" : "kobe" }  
  3. "_id" : ObjectId("5031144a50f2481577ea81e6"), "classid" : 1"age" : 23"name" : "nash" }  
  4. "_id" : ObjectId("5031145a50f2481577ea81e7"), "classid" : 2"age" : 18"name" : "james" }  
  5. "_id" : ObjectId("5031146a50f2481577ea81e8"), "classid" : 2"age" : 19"name" : "wade" }  
  6. "_id" : ObjectId("5031147450f2481577ea81e9"), "classid" : 2"age" : 19"name" : "bosh" }  
  7. "_id" : ObjectId("5031148650f2481577ea81ea"), "classid" : 2"age" : 25"name" : "allen" }  
  8. "_id" : ObjectId("5031149b50f2481577ea81eb"), "classid" : 1"age" : 19"name" : "howard" }  
  9. "_id" : ObjectId("503114a750f2481577ea81ec"), "classid" : 1"age" : 22"name" : "paul" }  
  10. "_id" : ObjectId("503114cd50f2481577ea81ed"), "classid" : 2"age" : 24"name" : "shane" }  
  11. >   

Map分组

Map函数必须调用emit(key,value)返回键值对,使用this访问当前待处理的Document。下面我们使用Map函数对students表按classid进行分组。

Js代码  收藏代码
  1. > map=function(){emit(this.classid,1)}  
  2. function () {  
  3.     emit(this.classid, 1);  
  4. }  
  5. >   

Reduce聚合

Reduce函数接收Map函数返回的结果作为参数,Map函数返回的键值序列组合成{key,[value1,value2,value3,……]}传递给reduce,代码如下:

Js代码  收藏代码
  1. > reduce=function(key,values){  
  2. ... var x = 0;  
  3. ... values.forEach(function(v){x+=v});  
  4. ... return x;  
  5. ... }  
  6. function (key, values) {  
  7.     var x = 0;  
  8.     values.forEach(function (v) {x += v;});  
  9.     return x;  
  10. }  
  11. >   

Reduce函数对values进行统计,从上面的代码可以看出Reduce函数主要是对1班和2班的记录数量进行求和运算。

Result获取结果  

Result函数的作用是用来获取计算后的结果,使用命令为:db.结果集.find()。其中的”结果集“可以通过out参数来指定。代码如下所示:

Js代码  收藏代码
  1. > result=db.runCommand({  
  2. ... mapreduce:"students",  
  3. ... map:map,  
  4. ... reduce:reduce,  
  5. ... out:"students_result"  
  6. ... });  
  7. {  
  8.     "result" : "students_result",  
  9.     "timeMillis" : 297,  
  10.     "counts" : {  
  11.         "input" : 9,  
  12.         "emit" : 9,  
  13.         "reduce" : 2,  
  14.         "output" : 2  
  15.     },  
  16.     "ok" : 1  
  17. }  
  18. > db.students_result.find()  
  19. "_id" : 1, "value" : 4 }  
  20. "_id" : 2, "value" : 5 }  
  21. >   

通过MapReduce处理后的结果存放在students_result集合中。

Finalize格式化输出

利用finalize()可以对reduce()的结果进行输出样式的格式化处理。代码如下:

Js代码  收藏代码
  1. > finalize=function(key,value){return {classid:key,count:value};}  
  2. function (key, value) {  
  3.     return {classid:key, count:value};  
  4. }  
  5. >   

定义好了finalize函数后,重新执行MapReduce,在函数定义中加入"finalize"参数,即可使用上面定义的finalize函数对返回结果进行格式化,代码如下:

Js代码  收藏代码
  1. > result=db.runCommand({  
  2. ... mapreduce:"students",  
  3. ... map:map,  
  4. ... reduce:reduce,  
  5. ... out:"students_result",  
  6. ... finalize:finalize  
  7. ... });  
  8. {  
  9.     "result" : "students_result",  
  10.     "timeMillis" : 137,  
  11.     "counts" : {  
  12.         "input" : 9,  
  13.         "emit" : 9,  
  14.         "reduce" : 2,  
  15.         "output" : 2  
  16.     },  
  17.     "ok" : 1  
  18. }  
  19. > db.students_result.find()  
  20. "_id" : 1, "value" : { "classid" : 1, "count" : 4 } }  
  21. "_id" : 2, "value" : { "classid" : 2, "count" : 5 } }  
  22. >   

Query对目标记录进行过滤

前面提到了MapReduce语法中有一个query参数是用来对目标集合进行条件过滤,我们只需要在result函数中加入"query"参数即可对结果集进行过滤,代码如下:

Js代码  收藏代码
  1. > result=db.runCommand({  
  2. ... mapreduce:"students",  
  3. ... map:map,  
  4. ... reduce:reduce,  
  5. ... out:"students_result",  
  6. ... finalize:finalize,  
  7. ... query:{age:{$gt:22}}  
  8. ... });  
  9. {  
  10.     "result" : "students_result",  
  11.     "timeMillis" : 776,  
  12.     "counts" : {  
  13.         "input" : 3,  
  14.         "emit" : 3,  
  15.         "reduce" : 1,  
  16.         "output" : 2  
  17.     },  
  18.     "ok" : 1  
  19. }  
  20. > db.students_result.find()  
  21. "_id" : 1, "value" : { "classid" : 1, "count" : 1 } }  
  22. "_id" : 2, "value" : { "classid" : 2, "count" : 2 } }  
  23. >   

从上面代码可以看到,我们在result函数中增加了query参数,只对age>22的document进行统计,输出结果每个班的人数就比原来的少了。


参考网址:http://chenzhou123520.iteye.com/blog/1637672


0 0