MongoDB的MapReduce使用

原文  http://xiaofancn.iteye.com/blog/1184712

 

参考文章

http://www.mongodb.org/display/DOCS/MapReduce

http://www.rainsts.net/article.asp?id=1044

https://github.com/mongodb/mongo-java-driver/commit/fa003adc5db8a6c4efe0279c74973af15d99e6ed#diff-2

MapReduce是一个编程模型,封装了并行计算、容错、数据分布、负载均衡等细节问题。

输入是一个key-value对的集合,中间输出也是key-value对的集合,用户使用两个函数:Map和Reduce。

在使用MongoDb的mapreduce功能时,我找Java代码找半天,结果练了半天的Javascript代码。

MongoDb是通过解析“Javascript”代码来计算的。所有我们先用Javascript代码调通,再使用Java代码拼接使用这个MapReduce功能。

Java代码 复制代码 收藏代码
  1. db.runCommand( 
  2.     mapreduce : <collection>, 
  3.     map : <mapfunction>, 
  4.     reduce : <reducefunction> 
  5.     [, query : <query filter object>] 
  6.     [, sort : <sort the query.  useful   optimization>] for 
  7.     [, limit : <number of objects to   from collection>] return 
  8.     [, out : <output-collection name>] 
  9.     [, keeptemp: < | >] true false 
  10.     [, finalize : <finalizefunction>] 
  11.     [, scope : <object where fields go into javascript global scope >] 
  12.     [, verbose :  ] true 
  13. }); 

参数说明:

  • mapreduce: 要操作的目标集合。
  • map: 映射函数 (生成键值对序列,作为 reduce 函数参数)。
  • reduce: 统计函数。
  • query: 目标记录过滤。
  • sort: 目标记录排序。
  • limit: 限制目标记录数量。
  • out: 统计结果存放集合 (不指定则使用临时集合,在客户端断开后自动删除)。
  • keeptemp: 是否保留临时集合。
  • finalize: 最终处理函数 (对 reduce 返回结果进行最终整理后存入结果集合)。
  • scope: 向 map、reduce、finalize 导入外部变量。
  • verbose: 显示详细的时间统计信息

先看看我们的文档结果


MongoDB的MapReduce使用_第1张图片

我使用上一篇文章插入数据 http://xiaofancn.iteye.com/blog/1163200

讲讲我们要实现的功能,就是按照名字name统计记录个数。

Java代码 复制代码 收藏代码
  1. D:\Program Files\mongodb>bin\mongo 
  2. MongoDB shell version: 2.0.0 
  3. connecting to: test 
  4. > use test; 
  5. switched to db test 
  6. > map = function() { 
  7. ... emit(this.name, {count:1}); 
  8. ... }; 
  9. function () { 
  10.     emit(this.name, {count:1}); 
  11. > reduce = function(key, values) { 
  12. ... var total = 0
  13. ... var index =0
  14. ... for(var i=0;i<values.length;i++){ 
  15. ...  total += values[i].count; 
  16. ...  index = i; 
  17. ... } 
  18. ... return {count:total}; 
  19. ... }; 
  20. function (key, values) { 
  21.     var total = 0
  22.     var index = 0
  23.     for (var i = 0; i < values.length; i++) { 
  24.         total += values[i].count; 
  25.         index = i; 
  26.     } 
  27.     return {count:total}; 
  28. > db.person.mapReduce(map, reduce, {out : "resultCollection"}); 
  29.         "result" : "resultCollection"
  30.         "timeMillis" : 112
  31.         "counts" : { 
  32.                 "input" : 10
  33.                 "emit" : 10
  34.                 "reduce" : 2
  35.                 "output" : 2 
  36.         }, 
  37.         "ok" : 1
  38. > db.resultCollection.find(); 
  39. { "_id" : "xiaofancn", "value" : { "count" : 3 } } 
  40. { "_id" : "小樊", "value" : { "count" : 7 } } 

Java代码 复制代码 收藏代码
  1. map = function() {  
  2.     emit(this.name, {count:1}); 
  3. }; 

     此函数是形成下面的key-values结构的,emit就是指定key和value的,也是结果的数据结构。

xiaofancn [{count:1},{count:1},{count:1}]

     由于name字段为xiaofancn的person有三个,所以形成三个{count:1}数组。

Java代码 复制代码 收藏代码
  1. reduce = function(key, values) { 
  2.     var total = 0
  3.     for(var i=0;i<values.length;i++){ 
  4.          total += values[i].count; 
  5.     } 
  6.     return {count:total}; 
  7. }; 

reduce函数中参数key和map函数的emit指定的key(this.name)是同一个key(name),values就是map函数形成的values( [{count:1},{count:1},{count:1}])

经过reduce函数处理就形成了key和一个最终的 {count:3}数据结构。定义好的函数,需要MongoDB执行

Java代码 复制代码 收藏代码
  1. db.person.mapReduce(map, reduce, {out : "resultCollection"}); 
  2. db.resultCollection.find(); 

  db代表当前的数据库,person当前的文档,mapReduce调用函数,out:是指定输出的文档名称。


MongoDB的MapReduce使用_第2张图片

好了,会使用Javascript,使用Java就是拼接我们的Javascript代码了。

Java代码 复制代码 收藏代码
  1. public void MapReduce() { 
  2.  
  3.         DBCollection personColl = mongoOperations.getCollection(mongoOperations 
  4.                 .getCollectionName(Person.class)); 
  5.         String map = "function() { emit(this.name, {count:1});}"
  6.          
  7.         String reduce = "function(key, values) {"
  8.         reduce=reduce+"var total = 0;"
  9.         reduce=reduce+"for(var i=0;i<values.length;i++){total += values[i].count;}"
  10.         reduce=reduce+"return {count:total};}"
  11.          
  12.         String result = "resultCollection"
  13.          
  14.         MapReduceOutput mapReduceOutput = personColl.mapReduce(map, 
  15.                 reduce.toString(), result, null); 
  16.         DBCollection resultColl = mapReduceOutput.getOutputCollection(); 
  17.         DBCursor cursor= resultColl.find(); 
  18.         while (cursor.hasNext()) { 
  19.             System.out.println(cursor.next()); 
  20.         } 
  21.     } 

你可能感兴趣的:(MongoDB的MapReduce使用)