MongoDB:MapReduce基础及实例

背景

MapReduce是个非常灵活和强大的数据聚合工具。它的好处是可以把一个聚合任务分解为多个小的任务,分配到多服务器上并行处理。

MongoDB也提供了MapReduce,当然查询语肯定是JavaScript。MongoDB中的MapReduce主要有以下几阶段:

1. Map:把一个操作Map到集合中的每一个文档

2. Shuffle: 根据Key分组对文档,并且为每个不同的Key生成一系列(>=1个)的值表(List of values)。

3. Reduce: 处理值表中的元素,直到值表中只有一个元素。然后将值表返回到Shuffle过程,循环处理,直到每个Key只对应一个值表,并且此值表中只有一个元素,这就是MR的结果。

4. Finalize:此步骤不是必须的。在得到MR最终结果后,再进行一些数据“修剪”性质的处理。

MongoDB中使用emit函数向MapReduce提供Key/Value对。

Reduce函数接受两个参数:Key,emits. Key即为emit函数中的Key。 emits是一个数组,它的元素就是emit函数提供的Value。

Reduce函数的返回结果必须要能被Map或者Reduce重复使用,所以返回结果必须与emits中元素结构一致。

Map或者Reduce函数中的this关键字,代表当前被Mapping文档。

实例

测试数据: 这个集合是三个用户购买的产品和产品价格的数据。

CodeCodefor(var i=0;i<1000;i++){
var rID=Math.floor(Math.random()*10);
var priceparseFloat((Math.random()*10).toFixed(2));
if(rID<4){
    db.test.insert({"user":"Joe","sku":rID,"price":price});
}
else if(rID>=4 && rID<7)
{
   db.test.insert({"user":"Josh","sku":rID,"price":price});
}
else {
db.test.insert({"user":"Ken","sku":rID,"price":price});
     }
}

1. 每个用户各购买了多少个产品?(单一Key做MR)

Code//SQL实现
select user,count(sku) from test
group by user

//MapReduce实现
map=function (){
 emit(this.user,{count:1})
}

reduce=function (key,values){
 var cnt=0;
values.forEach(function(val){ cnt+=val.count;});
return {"count":cnt};
}
//MR结果存到集合mr1
db.test.mapReduce(map,reduce,{out:"mr1"})
//查看MR之后结果
> db.mr1.find()
{ "_id" : "Joe", "value" : { "count" : 416 } }
{ "_id" : "Josh", "value" : { "count" : 287 } }
{ "_id" : "Ken", "value" : { "count" : 297 } }

2. 每个用户不同的产品购买了多少个?(复合Key做MR)

Code//SQL实现
select user,sku,count(*) from test
group by user,sku

//MapReduce实现
map=function (){
 emit({user:this.user,sku:this.sku},{count:1})
}

reduce=function (key,values){
 var cnt=0;
values.forEach(function(val){ cnt+=val.count;});
return {"count":cnt};
}

db.test.mapReduce(map,reduce,{out:"mr2"})
> db.mr2.find()
{ "_id" : { "user" : "Joe", "sku" : 0 }, "value" : { "count" : 103 } }
{ "_id" : { "user" : "Joe", "sku" : 1 }, "value" : { "count" : 106 } }
{ "_id" : { "user" : "Joe", "sku" : 2 }, "value" : { "count" : 102 } }
{ "_id" : { "user" : "Joe", "sku" : 3 }, "value" : { "count" : 105 } }
{ "_id" : { "user" : "Josh", "sku" : 4 }, "value" : { "count" : 87 } }
{ "_id" : { "user" : "Josh", "sku" : 5 }, "value" : { "count" : 107 } }
{ "_id" : { "user" : "Josh", "sku" : 6 }, "value" : { "count" : 93 } }
{ "_id" : { "user" : "Ken", "sku" : 7 }, "value" : { "count" : 98 } }
{ "_id" : { "user" : "Ken", "sku" : 8 }, "value" : { "count" : 83 } }
{ "_id" : { "user" : "Ken", "sku" : 9 }, "value" : { "count" : 116 } }

3. 每个用户购买的产品数量,总金额是多少?(复合Reduce结果处理)

Code//SQL实现
select user,count(sku),sum(price) from test
group by user

//MapReduce实现
map=function (){
  emit(this.user,{amount:this.price,count:1})
}

reduce=function (key,values){
 var res={amount:0,count:0}
values.forEach(function(val){
    res.amount+=val.amount;
    res.count+=val.count
});
return res;
}

db.test.mapReduce(map,reduce,{out:"mr3"})

> db.mr3.find()
{ "_id" : "Joe", "value" : { "amount" : 2053.8899999999994, "count" : 395 } }
{ "_id" : "Josh", "value" : { "amount" : 1409.2600000000002, "count" : 292 } }
{ "_id" : "Ken", "value" : { "amount" : 1547.7700000000002, "count" : 313 } }

4. 在3中返回的amount的float精度需要改成两位小数,还需要得到商品的平均价格。(使用Finalize处理reduce结果集)

Code//SQL实现
select user,cast(sum(price) as   decimal(10,   2)) as amount,count(sku) as [count],
cast((sum(price)/count(sku))  as decimal(10,2)) as avgPrice
from test
group by user
//MapReduce实现
map=function (){
  emit(this.user,{amount:this.price,count:1,avgPrice:0})
}

reduce=function (key,values){
 var res={amount:0,count:0,avgPrice:0}
values.forEach(function(val){
    res.amount+=val.amount;
    res.count+=val.count
});
return res;
}

finalizeFun=function (key,reduceResult){
 reduceResult.amount=(reduceResult.amount).toFixed(2);
 reduceResult.avgPrice=(reduceResult.amount/reduceResult.count).toFixed(2);
 return reduceResult;}

 db.test.mapReduce(map,reduce,{out:"mr4",finalize:finalizeFun})
> db.mr4.find()
{ "_id" : "Joe", "value" : { "amount" : "2053.89", "count" : 395, "avgPrice" : "5.20" } }
{ "_id" : "Josh", "value" : { "amount" : "1409.26", "count" : 292, "avgPrice" : "4.83" } }
{ "_id" : "Ken", "value" : { "amount" : "1547.77", "count" : 313, "avgPrice" : "4.94" } }

5. 统计单价大于6的SKU,每个用户的购买数量.(筛选数据子集做MR)

这个比较简单了,只需要将1.中调用MR时加上筛选查询即可,其它不变.

Codedb.test.mapReduce(map,reduce,{query:{price:{"$gt":6}},out:"mr5"})

总结

MongoDB中的MR工具非常强大,文中的例子只是基础实例.结合Sharding后,多服务器并行做数据集合处理,才能真正显现其能力.

如果后续有时间,希望能总结和分享更多关于MongoDB,关于SQL Server的东西.

时间: 2024-10-12 21:51:34

MongoDB:MapReduce基础及实例的相关文章

Hadoop初学指南(6)--MapReduce的简单实例及分析

本文在上一节的基础上通过一个简单的MR示例对MapReduce的运行流程进行分析. 假设有两行数据,分别是hello you,hello me,我们要统计其中出现的单词以及每个单词出现的次数. 所得的结果为 hello   2 you     1 me      1 (1)大致运行流畅 1.解析成2个<k,v>,分别是<0, hello you><10, hello me>.调用2次map函数. 2.执行map任务 3.map输出后的数据是:<hello,1>

MapReduce(一) mapreduce基础入门

一.mapreduce入门 1.什么是mapreduce 首先让我们来重温一下 hadoop 的四大组件:HDFS:分布式存储系统MapReduce:分布式计算系统YARN: hadoop 的资源调度系统Common: 以上三大组件的底层支撑组件,主要提供基础工具包和 RPC 框架等 Mapreduce 是一个分布式运算程序的编程框架,是用户开发"基于 hadoop 的数据分析 应用"的核心框架Mapreduce 核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的 分布式

安装使用Mongoose配合Node.js操作MongoDB的基础教程【转载】

这篇文章主要介绍了安装使用Mongoose来让Node.js操作MongoDB的基础教程,前端js+后端node+js操作MongoDB正是所谓最流行的一种JavaScript全栈开发方案,需要的朋友可以参考下 安装mongoose 使用express准备一个TestMongoDB项目,命令序列如下: express TestMongoDB cd TestMongoDB npm install 执行完上面的命令后,使用下面的命令安装mongoose: npm install mongoose -

SQL 查询基础(2)-实例

上次说到SQL查询语句的逻辑执行过程,现在来用一个实例说明一下逻辑执行的过程. 前提:我们有三个表,分别记住客户信息.订单信息和产品信息 客户信息表:Customer ID,Name,Adress,PhoneNumber ID Name Adress PhoneNumber 1 CompanyA No.1 Street 123456 2 CompanyB No.2 Street 23453 3 CompanyC No.3 Street 45321 4 CompanyD No.4 Street 4

C#基础与实例教程最简单的C#快速入门教程【转自:http://www.82011433.com/Html/?6982.html】

c#基础与实例教程最简单的C#快速入门教程 在一小时内学会C#.使用例程,简单却完整的探索C#语言的构造和特点.本文特别适合有C++基础却没有太多精力学习C#的读者. 简介 C#是一种具有C++特性,Java样式及BASIC快速建模特性的编程语言.如果你已经知晓C++语言,本文将在不到一小时的时间内带你快速浏览C#的语法.如果熟悉Java语言,Java的编程结构.打包和垃圾回收的概念肯定对你快速学习C#大有帮助.所以我在讨论C#语言构造的时候会假设你知道C++. c#基础与实例教程最简单的C#快

AutoCAD ObjectARX(VC)开发基础与实例教程2014版光盘镜像

AutoCAD ObjectARX(VC)开发基础与实例教程2014,最新版,光盘镜像 作者:张帆 朱文俊 编著 出版社:中国电力出版社 出版时间:2014年6月 点击一下

mongodb mapreduce用法

mongoDB的MapReduce简介 分类:            MongoDB2012-12-06 21:378676人阅读评论(2)收藏举报 MongoDB MapReduce MapReduce是一种计算模型,简单的说就是将大批量的工作(数据)分解(MAP)执行,然后再将结果合并成最终结果(REDUCE).这样做的好处是可以在任务被分解后,可以通过大量机器进行并行计算,减少整个操作的时间. 上面是MapReduce的理论部分,下面说实际的应用,下面以MongoDB MapReduce为

mongodb mapreduce使用总结

文章来自本人个人博客: mongodb mapreduce使用总结 ? 大家都知道,mongodb是一个非关系型数据库,也就是说,mongodb数据库中的每张表是独立存在的,表与表之间没有任何依赖关系.在mongodb中,除了各种CRUD语句之外,还给我们提供了聚合和mapreduce统计的功能,这篇文章主要来跟大家聊聊mongodb的mapreduce的操作. ?mapreduce的概念我就不赘述了,大家自己去查查吧. ?在mongodb中,mapreduce的语法如下: ? db.table

Java 找出四位数的全部吸血鬼数字 基础代码实例

/** * 找出四位数的全部吸血鬼数字 * 吸血鬼数字是指位数为偶数的数字,能够由一对数字相乘而得到,而这对数字各包括乘积的一半位数的数字,当中从最初的数字中选取的数字能够随意排序. * 以两个0结尾的数字是不同意的. *   比例如以下列数字都是吸血鬼数字 1260=21*60 1827=21*87 2187=27*81 ... * 比較笨的低效率的做法: 遍历全部四位数, 每生成一个四位数的时候, *         在双重循环遍历两位数,在两位数的内层循环中推断是否与最外层循环的四位数相等