千家信息网

MongoDB:MapReduce基础及实例

发表于:2024-10-23 作者:千家信息网编辑
千家信息网最后更新 2024年10月23日,背景MapReduce是个非常灵活和强大的数据聚合工具。它的好处是可以把一个聚合任务分解为多个小的任务,分配到多服务器上并行处理。MongoDB也提供了MapReduce,当然查询语肯定是JavaSc
千家信息网最后更新 2024年10月23日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 testgroup 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结果存到集合mr1db.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 testgroup 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 testgroup 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 avgPricefrom testgroup 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的东西.

结果 处理 函数 数据 产品 元素 用户 文档 实例 不同 强大 价格 任务 只有 就是 工具 数量 服务器 服务 查询 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 数据库搜索数据中带有通配符 小米云端数据库 西宁网络安全工程枝校在那里 如何把数据相互备份到数据库 安徽戴尔服务器系列云服务器 软件开发公司可以学编程吗 数据库对象怎么测试 服务器大秘境排行 三年级网络安全证文怎么写 尚线网络技术有限公司 大数据与网络安全的联系 深圳市指尖动力网络技术 服务器硬盘装笔记本电脑 如何构建ip服务器 华为网址拦截数据库是哪家的 工业网络安全态势感知 广西网络技术服务报价 r语言以行的形式输入数据库 网络安全法禁止渗透入侵 山东微派网络技术有限公司 路客互联网科技有限公司百科 樱花登录小工具显示服务器错误 用友t6连不上管理服务器 大屏线是接到服务器还是工作站 网络安全服务等级评定周期 果加智能锁服务器 品牌设计有什么服务器 java 软件开发流程 云计算技术中的数据库 山东服务器集团云空间
0