MongoDB mapReduce和Spring Data配合使用详解
来源 http://xiaofancn.iteye.com/blog/1184712
MapReduce是一个编程模型,封装了并行计算、容错、数据分布、负载均衡等细节问题。
输入是一个key-value对的集合,中间输出也是key-value对的集合,用户使用两个函数:Map和Reduce。
在使用MongoDb的mapreduce功能时,我找Java代码找半天,结果练了半天的Javascript代码。
MongoDb是通过解析“Javascript”代码来计算的。所有我们先用Javascript代码调通,再使用Java代码拼接使用这个MapReduce功能。
- db.runCommand(
- {
- mapreduce:<collection>,
- map:<mapfunction>,
- reduce:<reducefunction>
- [,query:<queryfilterobject>]
- [,sort:<sortthequery.usefuloptimization>]for
- [,limit:<numberofobjectstofromcollection>]return
- [,out:<output-collectionname>]
- [,keeptemp:<|>]truefalse
- [,finalize:<finalizefunction>]
- [,scope:<objectwherefieldsgointojavascriptglobalscope>]
- [,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统计记录个数。
- D:\ProgramFiles\mongodb>bin\mongo
- MongoDBshellversion:2.0.0
- connectingto:test
- >usetest;
- switchedtodbtest
- >map=function(){
- ...emit(this.name,{count:1});
- ...};
- function(){
- emit(this.name,{count:1});
- }
- >reduce=function(key,values){
- ...vartotal=0;
- ...varindex=0;
- ...for(vari=0;i<values.length;i++){
- ...total+=values[i].count;
- ...index=i;
- ...}
- ...return{count:total};
- ...};
- function(key,values){
- vartotal=0;
- varindex=0;
- for(vari=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}}
- map=function(){
- emit(this.name,{count:1});
- };
此函数是形成下面的key-values结构的,emit就是指定key和value的,也是结果的数据结构。
xiaofancn [{count:1},{count:1},{count:1}]
由于name字段为xiaofancn的person有三个,所以形成三个{count:1}数组。
- reduce=function(key,values){
- vartotal=0;
- for(vari=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执行
- db.person.mapReduce(map,reduce,{out:"resultCollection"});
- db.resultCollection.find();
db代表当前的数据库,person当前的文档,mapReduce调用函数,out:是指定输出的文档名称。
好了,会使用Javascript,使用Java就是拼接我们的Javascript代码了。
- publicvoidMapReduce(){
- DBCollectionpersonColl=mongoOperations.getCollection(mongoOperations
- .getCollectionName(Person.class));
- Stringmap="function(){emit(this.name,{count:1});}";
- Stringreduce="function(key,values){";
- reduce=reduce+"vartotal=0;";
- reduce=reduce+"for(vari=0;i<values.length;i++){total+=values[i].count;}";
- reduce=reduce+"return{count:total};}";
- Stringresult="resultCollection";
- MapReduceOutputmapReduceOutput=personColl.mapReduce(map,
- reduce.toString(),result,null);
- DBCollectionresultColl=mapReduceOutput.getOutputCollection();
- DBCursorcursor=resultColl.find();
- while(cursor.hasNext()){
- System.out.println(cursor.next());
- }
- }
MapReduce是一个编程模型,封装了并行计算、容错、数据分布、负载均衡等细节问题。
输入是一个key-value对的集合,中间输出也是key-value对的集合,用户使用两个函数:Map和Reduce。
在使用MongoDb的mapreduce功能时,我找Java代码找半天,结果练了半天的Javascript代码。
MongoDb是通过解析“Javascript”代码来计算的。所有我们先用Javascript代码调通,再使用Java代码拼接使用这个MapReduce功能。
- db.runCommand(
- {
- mapreduce:<collection>,
- map:<mapfunction>,
- reduce:<reducefunction>
- [,query:<queryfilterobject>]
- [,sort:<sortthequery.usefuloptimization>]for
- [,limit:<numberofobjectstofromcollection>]return
- [,out:<output-collectionname>]
- [,keeptemp:<|>]truefalse
- [,finalize:<finalizefunction>]
- [,scope:<objectwherefieldsgointojavascriptglobalscope>]
- [,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统计记录个数。
- D:\ProgramFiles\mongodb>bin\mongo
- MongoDBshellversion:2.0.0
- connectingto:test
- >usetest;
- switchedtodbtest
- >map=function(){
- ...emit(this.name,{count:1});
- ...};
- function(){
- emit(this.name,{count:1});
- }
- >reduce=function(key,values){
- ...vartotal=0;
- ...varindex=0;
- ...for(vari=0;i<values.length;i++){
- ...total+=values[i].count;
- ...index=i;
- ...}
- ...return{count:total};
- ...};
- function(key,values){
- vartotal=0;
- varindex=0;
- for(vari=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}}
- map=function(){
- emit(this.name,{count:1});
- };
此函数是形成下面的key-values结构的,emit就是指定key和value的,也是结果的数据结构。
xiaofancn [{count:1},{count:1},{count:1}]
由于name字段为xiaofancn的person有三个,所以形成三个{count:1}数组。
- reduce=function(key,values){
- vartotal=0;
- for(vari=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执行
- db.person.mapReduce(map,reduce,{out:"resultCollection"});
- db.resultCollection.find();
db代表当前的数据库,person当前的文档,mapReduce调用函数,out:是指定输出的文档名称。
好了,会使用Javascript,使用Java就是拼接我们的Javascript代码了。
- publicvoidMapReduce(){
- DBCollectionpersonColl=mongoOperations.getCollection(mongoOperations
- .getCollectionName(Person.class));
- Stringmap="function(){emit(this.name,{count:1});}";
- Stringreduce="function(key,values){";
- reduce=reduce+"vartotal=0;";
- reduce=reduce+"for(vari=0;i<values.length;i++){total+=values[i].count;}";
- reduce=reduce+"return{count:total};}";
- Stringresult="resultCollection";
- MapReduceOutputmapReduceOutput=personColl.mapReduce(map,
- reduce.toString(),result,null);
- DBCollectionresultColl=mapReduceOutput.getOutputCollection();
- DBCursorcursor=resultColl.find();
- while(cursor.hasNext()){
- System.out.println(cursor.next());
- }
- }
来源 http://xiaofancn.iteye.com/blog/1184712
MapReduce是一个编程模型,封装了并行计算、容错、数据分布、负载均衡等细节问题。
输入是一个key-value对的集合,中间输出也是key-value对的集合,用户使用两个函数:Map和Reduce。
在使用MongoDb的mapreduce功能时,我找Java代码找半天,结果练了半天的Javascript代码。
MongoDb是通过解析“Javascript”代码来计算的。所有我们先用Javascript代码调通,再使用Java代码拼接使用这个MapReduce功能。
- db.runCommand(
- {
- mapreduce:<collection>,
- map:<mapfunction>,
- reduce:<reducefunction>
- [,query:<queryfilterobject>]
- [,sort:<sortthequery.usefuloptimization>]for
- [,limit:<numberofobjectstofromcollection>]return
- [,out:<output-collectionname>]
- [,keeptemp:<|>]truefalse
- [,finalize:<finalizefunction>]
- [,scope:<objectwherefieldsgointojavascriptglobalscope>]
- [,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统计记录个数。
- D:\ProgramFiles\mongodb>bin\mongo
- MongoDBshellversion:2.0.0
- connectingto:test
- >usetest;
- switchedtodbtest
- >map=function(){
- ...emit(this.name,{count:1});
- ...};
- function(){
- emit(this.name,{count:1});
- }
- >reduce=function(key,values){
- ...vartotal=0;
- ...varindex=0;
- ...for(vari=0;i<values.length;i++){
- ...total+=values[i].count;
- ...index=i;
- ...}
- ...return{count:total};
- ...};
- function(key,values){
- vartotal=0;
- varindex=0;
- for(vari=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}}
- map=function(){
- emit(this.name,{count:1});
- };
此函数是形成下面的key-values结构的,emit就是指定key和value的,也是结果的数据结构。
xiaofancn [{count:1},{count:1},{count:1}]
由于name字段为xiaofancn的person有三个,所以形成三个{count:1}数组。
- reduce=function(key,values){
- vartotal=0;
- for(vari=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执行
- db.person.mapReduce(map,reduce,{out:"resultCollection"});
- db.resultCollection.find();
db代表当前的数据库,person当前的文档,mapReduce调用函数,out:是指定输出的文档名称。
好了,会使用Javascript,使用Java就是拼接我们的Javascript代码了。
- publicvoidMapReduce(){
- DBCollectionpersonColl=mongoOperations.getCollection(mongoOperations
- .getCollectionName(Person.class));
- Stringmap="function(){emit(this.name,{count:1});}";
- Stringreduce="function(key,values){";
- reduce=reduce+"vartotal=0;";
- reduce=reduce+"for(vari=0;i<values.length;i++){total+=values[i].count;}";
- reduce=reduce+"return{count:total};}";
- Stringresult="resultCollection";
- MapReduceOutputmapReduceOutput=personColl.mapReduce(map,
- reduce.toString(),result,null);
- DBCollectionresultColl=mapReduceOutput.getOutputCollection();
- DBCursorcursor=resultColl.find();
- while(cursor.hasNext()){
- System.out.println(cursor.next());
- }
- }
MapReduce是一个编程模型,封装了并行计算、容错、数据分布、负载均衡等细节问题。
输入是一个key-value对的集合,中间输出也是key-value对的集合,用户使用两个函数:Map和Reduce。
在使用MongoDb的mapreduce功能时,我找Java代码找半天,结果练了半天的Javascript代码。
MongoDb是通过解析“Javascript”代码来计算的。所有我们先用Javascript代码调通,再使用Java代码拼接使用这个MapReduce功能。
- db.runCommand(
- {
- mapreduce:<collection>,
- map:<mapfunction>,
- reduce:<reducefunction>
- [,query:<queryfilterobject>]
- [,sort:<sortthequery.usefuloptimization>]for
- [,limit:<numberofobjectstofromcollection>]return
- [,out:<output-collectionname>]
- [,keeptemp:<|>]truefalse
- [,finalize:<finalizefunction>]
- [,scope:<objectwherefieldsgointojavascriptglobalscope>]
- [,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统计记录个数。
- D:\ProgramFiles\mongodb>bin\mongo
- MongoDBshellversion:2.0.0
- connectingto:test
- >usetest;
- switchedtodbtest
- >map=function(){
- ...emit(this.name,{count:1});
- ...};
- function(){
- emit(this.name,{count:1});
- }
- >reduce=function(key,values){
- ...vartotal=0;
- ...varindex=0;
- ...for(vari=0;i<values.length;i++){
- ...total+=values[i].count;
- ...index=i;
- ...}
- ...return{count:total};
- ...};
- function(key,values){
- vartotal=0;
- varindex=0;
- for(vari=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}}
- map=function(){
- emit(this.name,{count:1});
- };
此函数是形成下面的key-values结构的,emit就是指定key和value的,也是结果的数据结构。
xiaofancn [{count:1},{count:1},{count:1}]
由于name字段为xiaofancn的person有三个,所以形成三个{count:1}数组。
- reduce=function(key,values){
- vartotal=0;
- for(vari=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执行
- db.person.mapReduce(map,reduce,{out:"resultCollection"});
- db.resultCollection.find();
db代表当前的数据库,person当前的文档,mapReduce调用函数,out:是指定输出的文档名称。
好了,会使用Javascript,使用Java就是拼接我们的Javascript代码了。
- publicvoidMapReduce(){
- DBCollectionpersonColl=mongoOperations.getCollection(mongoOperations
- .getCollectionName(Person.class));
- Stringmap="function(){emit(this.name,{count:1});}";
- Stringreduce="function(key,values){";
- reduce=reduce+"vartotal=0;";
- reduce=reduce+"for(vari=0;i<values.length;i++){total+=values[i].count;}";
- reduce=reduce+"return{count:total};}";
- Stringresult="resultCollection";
- MapReduceOutputmapReduceOutput=personColl.mapReduce(map,
- reduce.toString(),result,null);
- DBCollectionresultColl=mapReduceOutput.getOutputCollection();
- DBCursorcursor=resultColl.find();
- while(cursor.hasNext()){
- System.out.println(cursor.next());
- }
- }