MongoDB数据分析之MapReduce
2016-06-28 15:53
537 查看
1.关于数据类型:如果是使用控制台插入的数据,你插入的数字,很可能存成了Double,而想存成整型,则必须要用NumberInt()、NumberLong()
来,参考网址:http://www.cnblogs.com/lekko/p/3240028.html
2.MapReduce映射化简操作图:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/22/a8a598fcf30dad6ffabf6257d0a107e5)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/22/18de1cc0f454d3045b9ff9b0d6c1a383)
参考网址:http://wrox.cn/article/100035881/
3.MapReduce官网格式
db.runCommand(
{ mapreduce : <collection>,
map : <mapfunction>,
reduce : <reducefunction>,
out : <see output options below>
[, query : <query filter object>]
[, sort : <sorts the input objects using this key. Useful for optimization, like sorting by the emit key for fewer reduces>]
[, limit : <number of objects to return from collection, not supported with sharding>]
[, keeptemp: <true|false>]
[, finalize : <finalizefunction>]
[, scope : <object where fields go into javascript global scope >]
[, jsMode : true]
[, verbose : true]
}
);
参数说明:
mapreduce:要操作的目标集合
map:映射函数(生成键值对序列,作为Reduce函数的参数)
reduce:统计函数
query:目标记录过滤
sort:对目标记录排序
limit:限制目标记录数量
out:统计结果存放集合(如果不指定则使用临时集合,在客户端断开后自动删除)
keeptemp:是否保留临时集合
finalize:最终处理函数(对reduce返回结果执行最终整理后存入结
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/22/a8a598fcf30dad6ffabf6257d0a107e5)
果集合)
scope:向map、reduce、finalize导入外部变量
verbose:显示详细的时间统计信息
4.例子:对runoob数据库中class集合进行分组,统计各个班级的学生人数(或年龄大于22的人数)
应用场景:对students集合中的数据进行统计,根据classid显示每个班级的学生数量。初始数据如下:
Shell代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/fe33c3009b7b8306f07b0384ceef7219.png)
> db.students.find()
{ "_id" : ObjectId("5031143350f2481577ea81e5"), "classid" : 1, "age" : 20, "name" : "kobe" }
{ "_id" : ObjectId("5031144a50f2481577ea81e6"), "classid" : 1, "age" : 23, "name" : "nash" }
{ "_id" : ObjectId("5031145a50f2481577ea81e7"), "classid" : 2, "age" : 18, "name" : "james" }
{ "_id" : ObjectId("5031146a50f2481577ea81e8"), "classid" : 2, "age" : 19, "name" : "wade" }
{ "_id" : ObjectId("5031147450f2481577ea81e9"), "classid" : 2, "age" : 19, "name" : "bosh" }
{ "_id" : ObjectId("5031148650f2481577ea81ea"), "classid" : 2, "age" : 25, "name" : "allen" }
{ "_id" : ObjectId("5031149b50f2481577ea81eb"), "classid" : 1, "age" : 19, "name" : "howard" }
{ "_id" : ObjectId("503114a750f2481577ea81ec"), "classid" : 1, "age" : 22, "name" : "paul" }
{ "_id" : ObjectId("503114cd50f2481577ea81ed"), "classid" : 2, "age" : 24, "name" : "shane" }
>
Map分组
Map函数必须调用emit(key,value)返回键值对,使用this访问当前待处理的Document。下面我们使用Map函数对students表按classid进行分组。
Js代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/fe33c3009b7b8306f07b0384ceef7219.png)
> map=function(){emit(this.classid,1)}
function () {
emit(this.classid, 1);
}
>
Reduce聚合
Reduce函数接收Map函数返回的结果作为参数,Map函数返回的键值序列组合成{key,[value1,value2,value3,……]}传递给reduce,代码如下:
Js代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/fe33c3009b7b8306f07b0384ceef7219.png)
> reduce=function(key,values){
... var x = 0;
... values.forEach(function(v){x+=v});
... return x;
... }
function (key, values) {
var x = 0;
values.forEach(function (v) {x += v;});
return x;
}
>
Reduce函数对values进行统计,从上面的代码可以看出Reduce函数主要是对1班和2班的记录数量进行求和运算。
Result获取结果
Result函数的作用是用来获取计算后的结果,使用命令为:db.结果集.find()。其中的”结果集“可以通过out参数来指定。代码如下所示:
Js代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/fe33c3009b7b8306f07b0384ceef7219.png)
> result=db.runCommand({
... mapreduce:"students",
... map:map,
... reduce:reduce,
... out:"students_result"
... });
{
"result" : "students_result",
"timeMillis" : 297,
"counts" : {
"input" : 9,
"emit" : 9,
"reduce" : 2,
"output" : 2
},
"ok" : 1
}
> db.students_result.find()
{ "_id" : 1, "value" : 4 }
{ "_id" : 2, "value" : 5 }
>
通过MapReduce处理后的结果存放在students_result集合中。
Finalize格式化输出
利用finalize()可以对reduce()的结果进行输出样式的格式化处理。代码如下:
Js代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/fe33c3009b7b8306f07b0384ceef7219.png)
> finalize=function(key,value){return {classid:key,count:value};}
function (key, value) {
return {classid:key, count:value};
}
>
定义好了finalize函数后,重新执行MapReduce,在函数定义中加入"finalize"参数,即可使用上面定义的finalize函数对返回结果进行格式化,代码如下:
Js代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/fe33c3009b7b8306f07b0384ceef7219.png)
> result=db.runCommand({
... mapreduce:"students",
... map:map,
... reduce:reduce,
... out:"students_result",
... finalize:finalize
... });
{
"result" : "students_result",
"timeMillis" : 137,
"counts" : {
"input" : 9,
"emit" : 9,
"reduce" : 2,
"output" : 2
},
"ok" : 1
}
> db.students_result.find()
{ "_id" : 1, "value" : { "classid" : 1, "count" : 4 } }
{ "_id" : 2, "value" : { "classid" : 2, "count" : 5 } }
>
Query对目标记录进行过滤
前面提到了MapReduce语法中有一个query参数是用来对目标集合进行条件过滤,我们只需要在result函数中加入"query"参数即可对结果集进行过滤,代码如下:
Js代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/fe33c3009b7b8306f07b0384ceef7219.png)
> result=db.runCommand({
... mapreduce:"students",
... map:map,
... reduce:reduce,
... out:"students_result",
... finalize:finalize,
... query:{age:{$gt:22}}
... });
{
"result" : "students_result",
"timeMillis" : 776,
"counts" : {
"input" : 3,
"emit" : 3,
"reduce" : 1,
"output" : 2
},
"ok" : 1
}
> db.students_result.find()
{ "_id" : 1, "value" : { "classid" : 1, "count" : 1 } }
{ "_id" : 2, "value" : { "classid" : 2, "count" : 2 } }
>
从上面代码可以看到,我们在result函数中增加了query参数,只对age>22的document进行统计,输出结果每个班的人数就比原来的少了。
参考网址:http://chenzhou123520.iteye.com/blog/1637672
来,参考网址:http://www.cnblogs.com/lekko/p/3240028.html
2.MapReduce映射化简操作图:
参考网址:http://wrox.cn/article/100035881/
3.MapReduce官网格式
db.runCommand(
{ mapreduce : <collection>,
map : <mapfunction>,
reduce : <reducefunction>,
out : <see output options below>
[, query : <query filter object>]
[, sort : <sorts the input objects using this key. Useful for optimization, like sorting by the emit key for fewer reduces>]
[, limit : <number of objects to return from collection, not supported with sharding>]
[, keeptemp: <true|false>]
[, finalize : <finalizefunction>]
[, scope : <object where fields go into javascript global scope >]
[, jsMode : true]
[, verbose : true]
}
);
参数说明:
mapreduce:要操作的目标集合
map:映射函数(生成键值对序列,作为Reduce函数的参数)
reduce:统计函数
query:目标记录过滤
sort:对目标记录排序
limit:限制目标记录数量
out:统计结果存放集合(如果不指定则使用临时集合,在客户端断开后自动删除)
keeptemp:是否保留临时集合
finalize:最终处理函数(对reduce返回结果执行最终整理后存入结
果集合)
scope:向map、reduce、finalize导入外部变量
verbose:显示详细的时间统计信息
4.例子:对runoob数据库中class集合进行分组,统计各个班级的学生人数(或年龄大于22的人数)
应用场景:对students集合中的数据进行统计,根据classid显示每个班级的学生数量。初始数据如下:
Shell代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/fe33c3009b7b8306f07b0384ceef7219.png)
> db.students.find()
{ "_id" : ObjectId("5031143350f2481577ea81e5"), "classid" : 1, "age" : 20, "name" : "kobe" }
{ "_id" : ObjectId("5031144a50f2481577ea81e6"), "classid" : 1, "age" : 23, "name" : "nash" }
{ "_id" : ObjectId("5031145a50f2481577ea81e7"), "classid" : 2, "age" : 18, "name" : "james" }
{ "_id" : ObjectId("5031146a50f2481577ea81e8"), "classid" : 2, "age" : 19, "name" : "wade" }
{ "_id" : ObjectId("5031147450f2481577ea81e9"), "classid" : 2, "age" : 19, "name" : "bosh" }
{ "_id" : ObjectId("5031148650f2481577ea81ea"), "classid" : 2, "age" : 25, "name" : "allen" }
{ "_id" : ObjectId("5031149b50f2481577ea81eb"), "classid" : 1, "age" : 19, "name" : "howard" }
{ "_id" : ObjectId("503114a750f2481577ea81ec"), "classid" : 1, "age" : 22, "name" : "paul" }
{ "_id" : ObjectId("503114cd50f2481577ea81ed"), "classid" : 2, "age" : 24, "name" : "shane" }
>
Map分组
Map函数必须调用emit(key,value)返回键值对,使用this访问当前待处理的Document。下面我们使用Map函数对students表按classid进行分组。
Js代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/fe33c3009b7b8306f07b0384ceef7219.png)
> map=function(){emit(this.classid,1)}
function () {
emit(this.classid, 1);
}
>
Reduce聚合
Reduce函数接收Map函数返回的结果作为参数,Map函数返回的键值序列组合成{key,[value1,value2,value3,……]}传递给reduce,代码如下:
Js代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/fe33c3009b7b8306f07b0384ceef7219.png)
> reduce=function(key,values){
... var x = 0;
... values.forEach(function(v){x+=v});
... return x;
... }
function (key, values) {
var x = 0;
values.forEach(function (v) {x += v;});
return x;
}
>
Reduce函数对values进行统计,从上面的代码可以看出Reduce函数主要是对1班和2班的记录数量进行求和运算。
Result获取结果
Result函数的作用是用来获取计算后的结果,使用命令为:db.结果集.find()。其中的”结果集“可以通过out参数来指定。代码如下所示:
Js代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/fe33c3009b7b8306f07b0384ceef7219.png)
> result=db.runCommand({
... mapreduce:"students",
... map:map,
... reduce:reduce,
... out:"students_result"
... });
{
"result" : "students_result",
"timeMillis" : 297,
"counts" : {
"input" : 9,
"emit" : 9,
"reduce" : 2,
"output" : 2
},
"ok" : 1
}
> db.students_result.find()
{ "_id" : 1, "value" : 4 }
{ "_id" : 2, "value" : 5 }
>
通过MapReduce处理后的结果存放在students_result集合中。
Finalize格式化输出
利用finalize()可以对reduce()的结果进行输出样式的格式化处理。代码如下:
Js代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/fe33c3009b7b8306f07b0384ceef7219.png)
> finalize=function(key,value){return {classid:key,count:value};}
function (key, value) {
return {classid:key, count:value};
}
>
定义好了finalize函数后,重新执行MapReduce,在函数定义中加入"finalize"参数,即可使用上面定义的finalize函数对返回结果进行格式化,代码如下:
Js代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/fe33c3009b7b8306f07b0384ceef7219.png)
> result=db.runCommand({
... mapreduce:"students",
... map:map,
... reduce:reduce,
... out:"students_result",
... finalize:finalize
... });
{
"result" : "students_result",
"timeMillis" : 137,
"counts" : {
"input" : 9,
"emit" : 9,
"reduce" : 2,
"output" : 2
},
"ok" : 1
}
> db.students_result.find()
{ "_id" : 1, "value" : { "classid" : 1, "count" : 4 } }
{ "_id" : 2, "value" : { "classid" : 2, "count" : 5 } }
>
Query对目标记录进行过滤
前面提到了MapReduce语法中有一个query参数是用来对目标集合进行条件过滤,我们只需要在result函数中加入"query"参数即可对结果集进行过滤,代码如下:
Js代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/fe33c3009b7b8306f07b0384ceef7219.png)
> result=db.runCommand({
... mapreduce:"students",
... map:map,
... reduce:reduce,
... out:"students_result",
... finalize:finalize,
... query:{age:{$gt:22}}
... });
{
"result" : "students_result",
"timeMillis" : 776,
"counts" : {
"input" : 3,
"emit" : 3,
"reduce" : 1,
"output" : 2
},
"ok" : 1
}
> db.students_result.find()
{ "_id" : 1, "value" : { "classid" : 1, "count" : 1 } }
{ "_id" : 2, "value" : { "classid" : 2, "count" : 2 } }
>
从上面代码可以看到,我们在result函数中增加了query参数,只对age>22的document进行统计,输出结果每个班的人数就比原来的少了。
参考网址:http://chenzhou123520.iteye.com/blog/1637672
相关文章推荐
- 分享微信开发Html5轻游戏中的几个坑
- 如何在 Fedora 上安装 MongoDB 服务器
- PHP添加yaf xhprof mongodb 同理
- mongodb安装
- Hadoop_2.1.0 MapReduce序列图
- 如何在 Ubuntu 上安装 MongoDB
- 信息安全聚合 Sec-News 的重构之路
- perl操作MongoDB报错undefined symbol: HeUTF8解决方法
- C#中使用1.7版本驱动操作MongoDB简单例子
- 使用zabbix监控mongodb的方法
- Node.js的MongoDB驱动Mongoose基本使用教程
- MongoDB系列教程(四):设置用户访问权限
- node.js连接mongoDB数据库 快速搭建自己的web服务
- php实现的mongodb操作类实例
- 解决mongodb在ubuntu下启动失败,提示couldn‘t remove fs lock errno:9 Bad file descriptor的错误
- 在PostgreSQL的基础上创建一个MongoDB的副本的教程
- 关于mongoose连接mongodb重复访问报错的解决办法
- java操作mongodb示例分享
- php对mongodb的扩展(初出茅庐)
- 作为PHP程序员应该了解MongoDB的五件事