mongodb学习之五:聚合之group复习
来源:互联网 发布:淘宝网红直播费用 编辑:程序博客网 时间:2024/06/06 20:35
之前参照书中的例子进行学习group,以为有点懂了,想自己找个联系做做看,发现,原来并没有懂。今天再慢慢复习一下看看group的具体用法。
数据使用java循环插入3600条数据,结构比较统一,结构如下:
{ "_id" : ObjectId("5343a44474d0946a30cd26b1"), "name" : "赵小强", "sex" : "男", "age" : 39, "date" : "2010-9-14", "salary" : 8000, "dep" : "测试部"}
很简单,保存的是部门员工的信息。
1、求每个部门的平均工资
这个问题肯定得用group,因为要分组按照部门输出
db.runCommand({group:{ns:"emp",key:{"dep":true},initial:{avgSalary:0,sum:0,count:0},$reduce:function(doc,prev){prev.sum=prev.sum+doc.salary;prev.count++;},finalize:function(prev){prev.avgSalary = prev.sum/prev.count;delete prev.sum;delete prev.count;}}});输出结果:/* 0 */{ "retval" : [ { "dep" : "软件一部", "avgSalary" : 7509.505703422054 }, { "dep" : "工程实施部", "avgSalary" : 7214.285714285715 }, { "dep" : "软件二部", "avgSalary" : 7477.358490566037 }, { "dep" : "测试部", "avgSalary" : 7564.96062992126 }, { "dep" : "信息管理部", "avgSalary" : 7334 }, { "dep" : "运维部", "avgSalary" : 7293.50104821803 }, { "dep" : "人力资源部", "avgSalary" : 7275.142314990512 } ], "count" : 3600, "keys" : 7, "ok" : 1}
其实我一直迷惑的是叠加函数$reduce的编写。之前书中的例子中都使用了for循环,把我迷惑了。我没看清的是书中例子的for是循环的文档中某个数组类型的键
之所以叫叠加函数是因为,$reduce函数本身就是循环集合中的文档,不需要自己再写。自己需要写的只是每次循环你需要做的操作即可。
上面的例子中,初始文档定义了三个键:{avgSalary:0,sum:0,count:0},其实这个初始文档只是叠加的时候的初始文档,与最后输出的结果文档没太大的关系。
在$reduce函数中,我将salary进行叠加并计数,当叠加完成,还有使用最后的完成函数进行最后的过滤操作,将不必要的sum和count两个键删除。
2、统计每个部门的工资分布情况,部门总共多少人,以及每个部门的平均工资。按部门输出
db.runCommand({group:{ns:"emp",key:{"dep":true},initial:{salaryCount:{},sum:0,count:0,avgSalary:0},$reduce:function(doc,prev){if(doc.salary in prev.salaryCount){prev.salaryCount[doc.salary]++;}else{prev.salaryCount[doc.salary]=1;}prev.sum=prev.sum+doc.salary;prev.count++;},finalize:function(prev){prev.avgSalary = prev.sum/prev.count;delete prev.sum;}}});结果:/* 0 */{ "retval" : [ { "dep" : "软件一部", "salaryCount" : { "3000" : 57, "4000" : 56, "5000" : 55, "6000" : 52, "7000" : 55, "8000" : 59, "9000" : 84, "10000" : 53, "15000" : 55 }, "count" : 526, "avgSalary" : 7509.505703422054 }, { "dep" : "工程实施部", "salaryCount" : { "3000" : 60, "4000" : 55, "5000" : 57, "6000" : 69, "7000" : 75, "8000" : 54, "9000" : 63, "10000" : 54, "15000" : 45 }, "count" : 532, "avgSalary" : 7214.285714285715 }, { "dep" : "软件二部", "salaryCount" : { "3000" : 50, "4000" : 59, "5000" : 61, "6000" : 62, "7000" : 50, "8000" : 68, "9000" : 64, "10000" : 62, "15000" : 54 }, "count" : 530, "avgSalary" : 7477.358490566037 }, { "dep" : "测试部", "salaryCount" : { "3000" : 45, "4000" : 54, "5000" : 53, "6000" : 67, "7000" : 56, "8000" : 58, "9000" : 61, "10000" : 58, "15000" : 56 }, "count" : 508, "avgSalary" : 7564.96062992126 }, { "dep" : "信息管理部", "salaryCount" : { "3000" : 61, "4000" : 57, "5000" : 55, "6000" : 53, "7000" : 55, "8000" : 62, "9000" : 53, "10000" : 51, "15000" : 53 }, "count" : 500, "avgSalary" : 7334 }, { "dep" : "运维部", "salaryCount" : { "3000" : 51, "4000" : 56, "5000" : 50, "6000" : 53, "7000" : 57, "8000" : 54, "9000" : 52, "10000" : 65, "15000" : 39 }, "count" : 477, "avgSalary" : 7293.50104821803 }, { "dep" : "人力资源部", "salaryCount" : { "3000" : 61, "4000" : 65, "5000" : 63, "6000" : 57, "7000" : 49, "8000" : 66, "9000" : 52, "10000" : 63, "15000" : 51 }, "count" : 527, "avgSalary" : 7275.142314990512 } ], "count" : 3600, "keys" : 7, "ok" : 1}
3、接上面第二个例子,我只想看软件一部的统计信息,怎么办?
这就用到了可选的cond参数,这个参数就是用来过滤查询条件的
db.runCommand({group:{ns:"emp",key:{"dep":true},initial:{salaryCount:{},sum:0,count:0,avgSalary:0}, cond:{"dep":"软件一部"},$reduce:function(doc,prev){if(doc.salary in prev.salaryCount){prev.salaryCount[doc.salary]++;}else{prev.salaryCount[doc.salary]=1;}prev.sum=prev.sum+doc.salary;prev.count++;},finalize:function(prev){prev.avgSalary = prev.sum/prev.count;delete prev.sum;}}});结果:/* 0 */{ "retval" : [ { "dep" : "软件一部", "salaryCount" : { "3000" : 57, "4000" : 56, "5000" : 55, "6000" : 52, "7000" : 55, "8000" : 59, "9000" : 84, "10000" : 53, "15000" : 55 }, "count" : 526, "avgSalary" : 7509.505703422054 } ], "count" : 526, "keys" : 1, "ok" : 1}
4、统计每年公司新进员工数量,以年的形式输出
db.runCommand({group:{ns:"emp",$keyf:function(doc){return {year:doc.date.substr(0,4)};},initial:{empCount:0},$reduce:function(doc,prev){prev.empCount++;},finalize:function(prev){}}});结果:/* 0 */{ "retval" : [ { "year" : "2009", "empCount" : 761 }, { "year" : "2008", "empCount" : 736 }, { "year" : "2012", "empCount" : 682 }, { "year" : "2011", "empCount" : 699 }, { "year" : "2010", "empCount" : 722 } ], "count" : 3600, "keys" : 5, "ok" : 1}
上面这个例子演示了$keyf的使用。如果想自定义分组条件,则使用$keyf函数自定义。函数的参数是原文档,函数操作完后,返回的是自定义键的文档。
上面的例子中,我将文档中的date键的值进行截取,只留年份,返回是一个以year为键,以截取后的值为值的文档。
走完上面4个例子,对mongodb的group了解也慢慢明朗起来。以上的数据是我使用java循环插入的,结构比较整齐,因此在写$reduce函数时并没有对结构进行严谨的判断。只是简单的进行叠加等操作。
我也是刚开始学习,数据都是造的,包括问题和需求,在实际项目中遇到的问题可能要比这复杂的多的多,以后在实际项目中遇到什么问题再慢慢学习吧。
- mongodb学习之五:聚合之group复习
- MongoDB教程之聚合(count、distinct和group)
- mongodb学习记录之四:聚合
- Mongodb中数据聚合之基本聚合函数count、distinct、group
- MongoDB 笔记之 聚合
- MongoDB之聚合
- 【MongoDB】MongoDB之聚合框架
- MongoDB学习之旅五:MongoDB常用工具
- MongoDB 聚合Group(一)
- NoSQL数据库学习之MongoDB之group by 限制
- mongodb进阶二之mongodb聚合
- MongoDB学习之五----空间操作
- mongodb学习记录之五:mapreduce
- Solr分组聚合查询之Group
- MongoDB高级查询[聚合Group]
- MongoDB高级查询[聚合Group]
- MongoDB高级查询[聚合Group]
- 【mongodb系统学习之五】mongodb启动最常用参数
- 《程序员,你伤不起》读书笔记 (五) :当我彻底放弃自私自利后,前途变得一片光明,不能过多的只是关注自己的功夫,生活不能只局限在方寸虚拟世界里
- 内存监测工具DDMS-->Heap
- multiset的使用
- 微博文本情感分析-开篇
- Myeclipse生成doc文档时出现,编码 GBK 的不可映射字符
- mongodb学习之五:聚合之group复习
- sort()函数与qsort()函数及其头文件
- JIRA6.1.5 设置开机自启动 linux
- oracle数据类型
- 医药健康API开放接口
- C++深复制和浅复制
- Hdu 1163 Eddy's digital Roots + NYOJ-485 A*B Problem(九余数定理)
- X264 输出的统计值的含义(X264 Stats Output)
- 栈(顺序存储)C++模板实现