MongoDB的MapReduce使用

本文介绍如何使用MongoDB的MapReduce功能统计特定字段的记录数,并提供了详细的JavaScript及Java示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文 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. {
  3. mapreduce : <collection>,
  4. map : <mapfunction>,
  5. reduce : <reducefunction>
  6. [, query : <query filter object>]
  7. [, sort : <sort the query. useful optimization>] for
  8. [, limit : <number of objects to from collection>] return
  9. [, out : <output-collection name>]
  10. [, keeptemp: < | >] true false
  11. [, finalize : <finalizefunction>]
  12. [, scope : <object where fields go into javascript global scope >]
  13. [, verbose : ] true
  14. });
db.runCommand(
{
    mapreduce : <collection>,
    map : <mapfunction>,
    reduce : <reducefunction>
    [, query : <query filter object>]
    [, sort : <sort the query.  useful   optimization>] for
    [, limit : <number of objects to   from collection>] return
    [, out : <output-collection name>]
    [, keeptemp: < | >] true false
    [, finalize : <finalizefunction>]
    [, scope : <object where fields go into javascript global scope >]
    [, verbose :  ] true
});

参数说明:

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

先看看我们的文档结果


我使用上一篇文章插入数据 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. }
  12. > reduce = function(key, values) {
  13. ... var total = 0;
  14. ... var index =0;
  15. ... for(var i=0;i<values.length;i++){
  16. ... total += values[i].count;
  17. ... index = i;
  18. ... }
  19. ... return {count:total};
  20. ... };
  21. function (key, values) {
  22. var total = 0;
  23. var index = 0;
  24. for (var i = 0; i < values.length; i++) {
  25. total += values[i].count;
  26. index = i;
  27. }
  28. return {count:total};
  29. }
  30. > db.person.mapReduce(map, reduce, {out : "resultCollection"});
  31. {
  32. "result" : "resultCollection",
  33. "timeMillis" : 112,
  34. "counts" : {
  35. "input" : 10,
  36. "emit" : 10,
  37. "reduce" : 2,
  38. "output" : 2
  39. },
  40. "ok" : 1,
  41. }
  42. > db.resultCollection.find();
  43. { "_id" : "xiaofancn", "value" : { "count" : 3 } }
  44. { "_id" : "小樊", "value" : { "count" : 7 } }
D:\Program Files\mongodb>bin\mongo
MongoDB shell version: 2.0.0
connecting to: test
> use test;
switched to db test
> map = function() {
... emit(this.name, {count:1});
... };
function () {
    emit(this.name, {count:1});
}
> reduce = function(key, values) {
... var total = 0;
... var index =0;
... for(var i=0;i<values.length;i++){
...  total += values[i].count;
...  index = i;
... }
... return {count:total};
... };
function (key, values) {
    var total = 0;
    var index = 0;
    for (var i = 0; i < values.length; i++) {
        total += values[i].count;
        index = i;
    }
    return {count:total};
}
> db.person.mapReduce(map, reduce, {out : "resultCollection"});
{
        "result" : "resultCollection",
        "timeMillis" : 112,
        "counts" : {
                "input" : 10,
                "emit" : 10,
                "reduce" : 2,
                "output" : 2
        },
        "ok" : 1,
}
> db.resultCollection.find();
{ "_id" : "xiaofancn", "value" : { "count" : 3 } }
{ "_id" : "小樊", "value" : { "count" : 7 } }

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

此函数是形成下面的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 = function(key, values) {
	var total = 0;
	for(var i=0;i<values.length;i++){
		 total += values[i].count;
	}
	return {count:total};
};

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(map, reduce, {out : "resultCollection"});
db.resultCollection.find();

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


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

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

		DBCollection personColl = mongoOperations.getCollection(mongoOperations
				.getCollectionName(Person.class));
		String map = "function() { emit(this.name, {count:1});}";
		
		String reduce = "function(key, values) {";
		reduce=reduce+"var total = 0;";
		reduce=reduce+"for(var i=0;i<values.length;i++){total += values[i].count;}";
		reduce=reduce+"return {count:total};}";
		
		String result = "resultCollection";
		
		MapReduceOutput mapReduceOutput = personColl.mapReduce(map,
				reduce.toString(), result, null);
		DBCollection resultColl = mapReduceOutput.getOutputCollection();
		DBCursor cursor= resultColl.find();
		while (cursor.hasNext()) {
			System.out.println(cursor.next());
		}
	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值