博客
关于我
一篇文章带你搞定 MongoDB 中 MapReduce 使用
阅读量:353 次
发布时间:2019-03-04

本文共 5207 字,大约阅读时间需要 17 分钟。

玩过 Hadoop 的小伙伴对 MapReduce 应该不陌生,MapReduce 的强大且灵活,它可以将一个大问题分解为多个小问题,将各个小问题发送到不同的机器上去处理,所有的机器都完成计算后,再将计算结果合并为一个完整的解决方案,这就是所谓的分布式计算。此处我们就来看看 MongoDB 中 MapReduce 的使用。

文章目录

一、mapReduce

MongoDB 中的 MapReduce 可以用来实现更复杂的聚合命令,使用 MapReduce 主要实现两个函数:

map 函数和 reduce 函数,map 函数生成键值对序列,map 函数的结果作为 reduce 函数的参数,reduce函数中再做进一步的统计,某些我的数据集如下:

{   "_id" : ObjectId("59fa71d71fd59c3b2cd908d7"),"name" : "鲁迅","book" : "呐喊","price" : 38.0,"publisher" : "人民文学出版社"}{   "_id" : ObjectId("59fa71d71fd59c3b2cd908d8"),"name" : "曹雪芹","book" : "红楼梦","price" : 22.0,"publisher" : "人民文学出版社"}{   "_id" : ObjectId("59fa71d71fd59c3b2cd908d9"),"name" : "钱钟书","book" : "宋诗选注","price" : 99.0,"publisher" : "人民文学出版社"}{   "_id" : ObjectId("59fa71d71fd59c3b2cd908da"),"name" : "钱钟书","book" : "谈艺录","price" : 66.0,"publisher" : "三联书店"}{   "_id" : ObjectId("59fa71d71fd59c3b2cd908db"),"name" : "鲁迅","book" : "彷徨","price" : 55.0,"publisher" : "花城出版社"}

假如我想查询每位作者所出的书的总价,操作如下:

var map=function(){   emit(this.name,this.price)}var reduce=function(key,value){   return Array.sum(value)}var options={   out:"totalPrice"}db.sang_books.mapReduce(map,reduce,options);db.totalPrice.find()

emit 函数用于生成 key-value 数据集合emit(key, value); OR emit(key, {v1:v1, v2:v2});

第一个参数是key, 第二个参数是key对应的数据集合

emit 函数主要实现的分组,接收两个参数,第一个参数表示分组的分段,第二个参数表示要统计的数据,减少做特定的数据处理操作,接收两个参数,对应的 emit 方法的两个参数,此处使用了 Array 中的sum 对 price 分段进行自加处理,options 中定义了将结果输出的集合,届时我们将在此集合中去查询数据,很少情况下,这个集合即使在数据库重启后也会保留,并保留集合中的数据。

查询结果如下:

{       "_id" : "曹雪芹",    "value" : 22.0}{       "_id" : "钱钟书",    "value" : 165.0}{       "_id" : "鲁迅",    "value" : 93.0}

再加上我想查询每位作者出了几本书,如下:

var map=function(){   emit(this.name,1)}var reduce=function(key,value){   return Array.sum(value)}var options={   out:"bookNum"}db.sang_books.mapReduce(map,reduce,options);db.bookNum.find()

查询结果如下:

{       "_id" : "曹雪芹",    "value" : 1.0}{       "_id" : "钱钟书",    "value" : 2.0}{       "_id" : "鲁迅",    "value" : 2.0}

将每位作者的书列出来,如下:

var map=function(){   emit(this.name,this.book)}var reduce=function(key,value){   return value.join(',')}var options={   out:"books"}db.sang_books.mapReduce(map,reduce,options);db.books.find()

结果如下:

{       "_id" : "曹雪芹",    "value" : "红楼梦"}{       "_id" : "钱钟书",    "value" : "宋诗选注,谈艺录"}{       "_id" : "鲁迅",    "value" : "呐喊,彷徨"}

例如查询每个人体重在¥ 40以上的书:

var map=function(){   emit(this.name,this.book)}var reduce=function(key,value){   return value.join(',')}var options={   query:{   price:{   $gt:40}},out:"books"}db.sang_books.mapReduce(map,reduce,options);db.books.find()

查询表示对查到的集合再进行筛选。

结果如下:

{       "_id" : "钱钟书",    "value" : "宋诗选注,谈艺录"}{       "_id" : "鲁迅",    "value" : "彷徨"}

二、runCommand 实现

我们也可以利用 runCommand 命令来执行 MapReduce。格式如下:

db.runCommand(               {                    mapReduce: 
, map:
, reduce:
, finalize:
, out:
, query:
, sort:
, limit:
, scope:
, jsMode:
, verbose:
, bypassDocumentValidation:
, collation:
} )

含义如下:

参数 意味着
mapReduce 表示要操作的集合
map map函数
reduce reduce函数
finalize 最终处理函数
out 输出的集合
query 对结果进行过滤
sort 对结果排序
limit 返回的结果数
scope 设置参数值,在这里设置的值在map,reduce,finalize函数中可见
jsMode 是否将地图执行的中间数据由javascript对象转换成BSON对象,替换为false
verbose 是否显示详细的时间统计信息
bypassDocumentValidation 是否绕过文档验证
collation 其他一些校对

如下操作,表示执行MapReduce操作重新统计的集合限制返回条数,限制返回条数之后再进行统计操作,如下:

var map=function(){   emit(this.name,this.book)}var reduce=function(key,value){   return value.join(',')}db.runCommand({   mapreduce:'sang_books',map,reduce,out:"books",limit:4,verbose:true})db.books.find()

执行结果如下:

{       "_id" : "曹雪芹",    "value" : "红楼梦"}{       "_id" : "钱钟书",    "value" : "宋诗选注,谈艺录"}{       "_id" : "鲁迅",    "value" : "呐喊"}

小伙伴们看到,鲁迅在一本书不见了,就是因为limit是先限制集合返回条数,然后再执行统计操作。

finalize 操作表示最终处理函数,如下:

var f1 = function(key,reduceValue){   var obj={   };obj.author=key;obj.books=reduceValue; return obj}var map=function(){   emit(this.name,this.book)}var reduce=function(key,value){   return value.join(',')}db.runCommand({   mapreduce:'sang_books',map,reduce,out:"books",finalize:f1})db.books.find()

f1 第一个参数键表示emit中的第一个参数,第二个参数表示reduce的执行结果,我们可以在f1中对这个结果进行再处理,结果如下:

{       "_id" : "曹雪芹",    "value" : {           "author" : "曹雪芹",        "books" : "红楼梦"    }}{       "_id" : "钱钟书",    "value" : {           "author" : "钱钟书",        "books" : "宋诗选注,谈艺录"    }}{       "_id" : "鲁迅",    "value" : {           "author" : "鲁迅",        "books" : "呐喊,彷徨"    }}

scope则可以用来定义一个在地图,reduce和finalize中都可见的变量,如下:

var f1 = function(key,reduceValue){   var obj={   };obj.author=key;obj.books=reduceValue;obj.sang=sang; return obj}var map=function(){   emit(this.name,this.book)}var reduce=function(key,value){   return value.join(',--'+sang+'--,')}db.runCommand({   mapreduce:'sang_books',map,reduce,out:"books",finalize:f1,scope:{   sang:"haha"}})db.books.find()

执行结果如下:

{       "_id" : "曹雪芹",    "value" : {           "author" : "曹雪芹",        "books" : "红楼梦",        "sang" : "haha"    }}{       "_id" : "钱钟书",    "value" : {           "author" : "钱钟书",        "books" : "宋诗选注,--haha--,谈艺录",        "sang" : "haha"    }}{       "_id" : "鲁迅",    "value" : {           "author" : "鲁迅",        "books" : "呐喊,--haha--,彷徨",        "sang" : "haha"    }}

转载地址:http://xdar.baihongyu.com/

你可能感兴趣的文章
mysql中出现update-alternatives: 错误: 候选项路径 /etc/mysql/mysql.cnf 不存在 dpkg: 处理软件包 mysql-server-8.0的解决方法(全)
查看>>
Mysql中各类锁的机制图文详细解析(全)
查看>>
MySQL中地理位置数据扩展geometry的使用心得
查看>>
Mysql中存储引擎简介、修改、查询、选择
查看>>
Mysql中存储过程、存储函数、自定义函数、变量、流程控制语句、光标/游标、定义条件和处理程序的使用示例
查看>>
mysql中实现rownum,对结果进行排序
查看>>
mysql中对于数据库的基本操作
查看>>
Mysql中常用函数的使用示例
查看>>
MySql中怎样使用case-when实现判断查询结果返回
查看>>
Mysql中怎样使用update更新某列的数据减去指定值
查看>>
Mysql中怎样设置指定ip远程访问连接
查看>>
mysql中数据表的基本操作很难嘛,由这个实验来带你从头走一遍
查看>>
Mysql中文乱码问题完美解决方案
查看>>
mysql中的 +号 和 CONCAT(str1,str2,...)
查看>>
Mysql中的 IFNULL 函数的详解
查看>>
mysql中的collate关键字是什么意思?
查看>>
MySql中的concat()相关函数
查看>>
mysql中的concat函数,concat_ws函数,concat_group函数之间的区别
查看>>
MySQL中的count函数
查看>>
MySQL中的DB、DBMS、SQL
查看>>