MongoDB 如何对子文档分段统计

按指定的分段区间进行分组,统计各段内的数据量。如有成绩集合 scores,按成绩分段,分别统计语文、英文成绩各分数段的人数,相关的数据如下:
成绩分段划分为:[60, 70, 80, 90]
也就是按小于 60, 60—70, 70—80,80—90, 大于 90 分段(
区间左闭右开)。

name   age province subject
zhou gao gao 24 guang xi [Chinese,80],[Math,84][English,84],[Chemic,98]
li chao 16 shan dong [Chinese,94],[Math,88][English ,75],[Chemic,73]
yang hao hao 26 guang xi [Chinese,85],[Math,83][English ,64],[Chemic,71]
  期望结果如下:
Segment Chinese English
0 3 5
1
2
3
4
用 MongoDB 脚本实现思路,由于没有提供相关的接口,可使用 MapReduce 遍历每一行数据,针对不同学科分段成绩分别进行计数,实现比较复杂。

可以使用集算器, 按学科成绩分段计数后合并数据,实现比较容易。
集算器安装包可去润乾网站下载,运行时需要一个授权,免费版本就够用。

我们将上述事例实现步骤:

1、在集算器中编写脚本 score.dfx

A B
1 [60, 70, 80, 90] / 分段数据
2 =mongo_open("mongodb://127.0.0.1:27017/raqdb") / 连接 MongDB 数据库
3 =mongo_shell(A1,"scores.find(,{_id:0})") / 获取集合 score 数据
4 =A3.groups(A1.pseg(subject.(score)(1)):Segment;   count(1): Chinese ) / 统计语文各段成绩人数
5 =A3.groups(A1.pseg(subject.(score)(3)):Segment;   count(1): English) / 统计英文各段成绩人数
6 =A4.join(Segment, A5:Segment,   English) / 合并数据,将英语追加到 A4
7 >A1.close() / 关闭连接
  2、 执行脚本返回结果:
A6 Segment Chinese English
0 1 3
1 2 3
2 8 5
3 6 8
4 3 1

pseg 返回各成绩所在的分段号, 针对不同的成绩按分段号进行计数

集算器提供了 JDBC 接口,脚本 score.dfx 很容易集成到 Java 中:

public static void doWork() {

    Connection con = null;
    java.sql.Statement st;
   
    try{
        Class.forName("com.esproc.jdbc.InternalDriver");
        con = DriverManager.getConnection("jdbc:esproc:local://"); 
        // 调用脚本 score.dfx
        st=con.createStatement(); 
        ResultSet rst = st.executeQuery("call score");
        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 脚本》。