MongoDB 怎么实现交叉汇总
交叉表作为一种常用的分类汇总表格,它可以用来显示表中某个字段的汇总值,并将它们分组;通过某一变量分组后作为行,然后用其它变量或变量的组合作为列,形成数据表进行统计分析。
如有集合 events, 统计每个用户的各个事件的数量;按不同的人汇总事件数到表最后一列,按各事件汇总到最后一行,相关的数据与汇总表如下:
UserID | EventID | Count | Date |
1 | 1 | 10 | 2020-01-02 |
1 | 1 | 15 | 2020-01-02 |
1 | 2 | 12 | 2020-01-02 |
1 | 3 | 18 | 2020-01-03 |
2 | 1 | 5 | 2020-01-02 |
3 | 2 | 10 | 2020-01-02 |
UserID | Evt1 | Evt2 | Evt3 | Events |
1 | 25 | 12 | 18 | 55 |
… | … | |||
… | … | |||
Total | 30.0 | 60.0 | 60.0 | 70.0 |
用 MongoDB 脚本实现思路,针对每一个文档将每个事件的数据对齐,并增加字段记录当前事件数,相当于整理数据;再按用户分组,对各事件数量累计;按列数据累计追加到集合最后一行,最后过滤列显示,实现比较复杂。
可以使用集算器, 按人分组后进行汇总,实现比较容易。
集算器安装包可去润乾网站下载,运行时需要一个授权,免费版本就够用。
我们将上述事例实现步骤:
1、在集算器中编写脚本 events.dfx:
A | B | |
1 | =mongo_open("mongodb://127.0.0.1:27017/raqdb") | / 连接 MongDB 数据库 |
2 | =mongo_shell(A1,"events.find(,{_id:0})") | / 获取集合 events 数据 |
3 | =A2.pivot@s(UserID;EventID,sum(Count); 1:"Evt1",2:"Evt2", 3:"Evt3").derive(Evt1+Evt2+Evt3:Events) | / 按 UserID 分组统计 EventID 事件并汇总 |
4 | >A3.insert(0, "Total", A3.sum(Evt1), A3.sum(Evt2), A3.sum(Evt3), A3.sum(Events)) | / 按各事件汇总追加到序列 |
5 | >A1.close() | / 关闭连接 |
A3 | UserID | Evt1 | Evt2 | Evt3 | Events |
1 | 25 | 12 | 18 | 55 | |
2 | 5 | (null) | (null) | 5 | |
3 | (null) | 10 | (null) | 10 | |
Total | 30 | 22 | 18 | 70 |
A3:按 UserID 分组,先得到本组的各个 EventID 事件数量,再汇总。
集算器提供了 JDBC 接口,脚本 events.dfx 很容易集成到 Java 中:
public static void doWork() {
java.sql.Statement st;
try{
Class.forName("com.esproc.jdbc.InternalDriver");
con = DriverManager.getConnection("jdbc:esproc:local://");
// 调用脚本 events.dfx
st=con.createStatement();
ResultSet rst = st.executeQuery("call events");
System.out.println(rst);
} catch(Exception e){
System.out.println(e);
} finally{
// 关闭连接
if (con!= null) {
try {
con.close();
} catch(Exception e) {
System.out.println(e);
}
}
}
}
集算器与 JAVA 集成的进一步信息可参考:《Java 如何调用 SPL 脚本》。
英文版