MongoDB 在进行分组统计时如果面对一些比较繁芜的打算情形,每每会碰着 shell 脚本过于繁芜的问题。而集算器 SPL 措辞,则因其有丰富的函数库及易用性恰好能填补 Mongo 这方面的不敷。若想理解更多,请前往乾学院:MongoDB 分组统计!
MongoDB 作为 NoSql 文档型数据库,在环球范围得到广泛的支持与运用。在比较常用的数据库功能中,相对付普通的增编削查,利用 group 聚合分组统计有些繁芜,而 MongoDB 也给予了支持。本文将对MongoDb分组的实现方法及示例进行剖析,通过在 MongoDB 脚本中操作、利用集算器 SPL 措辞操作两种操作路子,进行大略的归纳总结。详细的问题场景包括以下几个方面:
1. 内嵌数组构造的统计
2. 内嵌文档求和
3. 分段分组构造统计
4. 多字段分组统计
1. 内嵌数组构造的统计
对嵌套数组构造中的数据进行统计处理例如查询考试科目的均匀分及每个学生的总成绩:
测试数据:
期待统计结果:
Mongodb脚本:
由于各科分数 scroe 是按课目、成绩记录的数组构造,统计前须要将它拆解,将每科成绩与学生对应,然后再实现分组打算。这须要熟习 unwind 与 group 组合的运用。
SPL 脚本 (student.dfx):
按课目统计的总分数:
每个学生的总成绩:
脚本解释:
A1:连接 mongodb 数据库。
A2:获取 student 表中的数据。
A3:将 scroe 数据合并成序表,再按课程分组,打算均匀分。
A4:统计每个学生的成绩后返回列名为 NAME、TOTAL 的序表。new 函数表示天生新序表。
A5:关闭数据库连接。
这个嵌套构造统计的例子比较常见,相信很多人都碰着过,须要先拆解再分组打算,紧张是熟习 mongodb 对嵌套数据构造的处理。
2. 内嵌文档求和
对内嵌文档中的数据求和处理, 例如统计下面每条记录中 income,output 的数量和。
测试数据:
期待统计结果:
Mongodb脚本:
var fields = [ \"大众income\"大众, \"大众output\"大众];
db.computer.aggregate([
{
$project:{
\"大众values\公众:{
$filter:{
input:{
\公众$objectToArray\"大众:\"大众$$ROOT\公众
},
cond:{
$in:[
\"大众$$this.k\公众,
fields
]
}
}
}
}
},
{
$unwind:\"大众$values\公众
},
{
$project:{
key:\"大众$values.k\"大众,
values:{
\"大众$sum\"大众:{
\"大众$let\公众:{
\公众vars\"大众:{
\"大众item\"大众:{
\"大众$objectToArray\"大众:\"大众$values.v\"大众
}
},
\"大众in\公众:\公众$$item.v\"大众
}
}
}
}
},
{$sort: {\公众_id\"大众:-1}},
{ \"大众$group\"大众: {
\公众_id\公众: \"大众$_id\"大众,
'income':{\"大众$first\公众: \"大众$values\公众},
\公众output\公众:{\"大众$last\"大众: \"大众$values\"大众}
}},
]);
filter将income,output 部分信息存放到数组中,用 unwind 拆解成记录,再累计各项值求和,按 _id 分组合并数据。
SPL脚本:
统计结果
脚本解释:
A1:连接数据库
A2:获取 computer 表中的数据
A3:将 income、output 字段中的数据分别转换成序列求和,再与 ID 组合天生新序表
A4:关闭数据库连接。
获取子记录的字段值,然后求和,相对付 mongo 脚本简化了不少。这个内嵌文档与内嵌数组在组织构造上有点类似,欠妥心随意马虎稠浊,因此须要特殊把稳与上例中的 scroe 数组构造比较,写出的脚本有所不同。
3. 分段分组构造统计
统计各段内的记录数量。例如下面按发卖量分段,统计各段内的数据量,数据如下:
分段方法:0-3000;3000-5000;5000-7500;7500-10000;10000 以上。
期望结果:
Mongo 脚本
这个需求按条件分段分组,mongodb 没有供应对应的 api,实现起来有点繁琐,上面的程序是个中实现的一个例子参考,当然也可以写成其它实现形式。下面看看集算器脚本的实现。
SPL脚本:
脚本解释:
A1:定义 SALES 分组区间。
A2:连接 mongodb 数据库。
A3:获取 sales 表中的数据。
A4:根据 SALES 区间分组统计员工数。个中函数 pseg()表示返回成员在序列中的区段序号,int() 表示转换成整数。
A5:关闭数据库连接。
Mongodb脚本与 SPL 脚本都实现了预期的结果,但函数pseg 的利用让 SPL 脚本精简了不少。
4. 多字段分组统计
统计分类项下的总数及各子项数。下面统计按 addr 分类的 book 的数量以及其下不同 book 类型的数量。
期望结果:
Mongo脚本
先按 addr,book 分组统计 book 数,再按 addr 分组统计 book 数,调度显示顺序。
SPL脚本 (books.dfx):
打算结果:
脚本解释:
A1:连接 mongodb 数据库。
A2:获取 books 表中的数据。
A3:按 addr,book 分组统计 book 数顾。
A4:再按 addr 分组统计 book 数。
A5:将 A4 中的 Total 按 addr 关联后合并到序表中。
B5: 返回序表 A5。
A6:关闭数据库连接。
这个例子中的 SPL 脚本除了一如既往的精简清晰外,还显示了如何大略方便地与 Java 程序集成。
在 Java 程序中如果要对 MongoDB 实现上面的分组统计功能,须要根据不同的需求重新一五一十地实现,比较麻烦的同时也不通用。而如果用集算器来实现就随意马虎多了,集算器供应了 JDBC 驱动程序,支持在 Java 程序中用 JDBC 存储过程办法访问打算结果,调用方法与调用存储过程相同。(JDBC 详细配置参考《集算器教程》中的“JDBC基本利用”章节)
Java 调用紧张过程如下:
public void testStudent (){
Connection con = null;
com.esproc.jdbc.InternalCStatement st;
try{
// 建立连接
Class.forName(\公众com.esproc.jdbc.InternalDriver\公众);
con= DriverManager.getConnection(\公众jdbc:esproc:local://\"大众);
//调用存储过程,个中books是 dfx 的文件名
st =(com. esproc.jdbc.InternalCStatement)con.prepareCall(\"大众call books ()\"大众);
//实行存储过程
st.execute();
// 获取结果集
ResultSet rs = st.getResultSet();
。。。。。。。
catch(Exception e){
System.out.println(e);
}
可以看到,集算器的打算结果能够很方便地供 Java 运用程序利用。除了上面的调用办法,程序也可以修正成直接加载 SPL 脚本的函数,用 SPL 脚本文件名当参数来实现。同时,集算器也支持 ODBC 驱动,与其它支持 ODBC 的措辞集成也与此类似。
大略总结一下,MongoDB 的聚合分组打算的操作与存储文档的构造息息相关,丰富的文档构造一方面有利于存储,同时数据查询展示也可以做到多样化,但另一方面也带来了 shell 脚本操作的繁芜性,写起来比较不随意马虎, 须要考虑的细节、步骤也比较多。通过上面这几个大略案例的剖析比较,可以看到集算器 SPL 在实现分组统计方面能简化操作,降落难度,从而有效地帮助我们办理问题。