开发者社区> 润乾软件> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

MongoDB 分组统计

简介:    MongoDB 作为 NoSql 文档型数据库,在全球范围得到广泛的支持与应用。在比较常用的数据库功能中,相对于普通的增删改查,使用 group 聚合分组统计有些复杂,而 MongoDB 也给予了支持。
+关注继续查看

   MongoDB 作为 NoSql 文档型数据库,在全球范围得到广泛的支持与应用。在比较常用的数据库功能中,相对于普通的增删改查,使用 group 聚合分组统计有些复杂,而 MongoDB 也给予了支持。本文将对MongoDb分组的实现方法及示例进行分析,通过在 MongoDB 脚本中操作、使用集算器 SPL 语言操作两种操作途径,进行简单的归纳总结。具体的问题场景包括以下几个方面:

  1. 内嵌数组结构的统计........................................................................... 1
  2. 内嵌文档求和..................................................................................... 2
  3. 分段分组结构统计.............................................................................. 4
  4. 多字段分组统计................................................................................. 6
  5. 内嵌数组结构的统计
    对嵌套数组结构中的数据进行统计处理例如查询考试科目的平均分及每个学生的总成绩:

测试数据:
1
00

由于各科分数 scroe 是按课目、成绩记录的数组结构,统计前需要将它拆解,将每科成绩与学生对应,然后再实现分组计算。这需要熟悉 unwind 与 group 组合的应用。
2
脚本说明:
       A1:连接 mongodb 数据库。
       A2:获取 student 表中的数据。
       A3:将 scroe 数据合并成序表,再按课程分组,计算平均分。
       A4:统计每个学生的成绩后返回列名为 NAME、TOTAL 的序表。new 函数表示生成新序表。
       A5:关闭数据库连接。

   这个嵌套结构统计的例子比较常见,相信很多人都遇到过,需要先拆解再分组计算,主要是熟悉 mongodb 对嵌套数据结构的处理。

  1. 内嵌文档求和
    对内嵌文档中的数据求和处理, 例如统计下面每条记录中 income,output 的数量和。

测试数据:
3
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"}
    }},
]);
oe 是按课目、成绩记录的数组结构,统计前需要将它拆解,将每科成绩与学生对应,然后再实现分组计算。这需要熟悉 unwind 与 group 组合的应用。
SPL 脚本 (student.dfx):
filter将income,output 部分信息存放到数组中,用 unwind 拆解成记录,再累计各项值求和,按 _id 分组合并数据。

SPL脚本:
3
脚本说明:
      A1:连接数据库
      A2:获取 computer 表中的数据
      A3:将 income、output 字段中的数据分别转换成序列求和,再与 ID 组合生成新序表
      A4:关闭数据库连接。

   获取子记录的字段值,然后求和,相对于 mongo 脚本简化了不少。这个内嵌文档与内嵌数组在组织结构上有点类似,不小心容易混淆,因此需要特别注意与上例中的 scroe 数组结构比较,写出的脚本有所不同。

  1. 分段分组结构统计
    统计各段内的记录数量。例如下面按销售量分段,统计各段内的数据量,数据如下:

4
Mongo 脚本
var a_count=0;
var b_count=0;
var c_count=0;
var d_count=0;
var e_count=0;
db.sales.find({
}).forEach(
    function(myDoc) {
        if (myDoc.SALES <3000)   {
            a_count += 1;
        }
        else if (myDoc.SALES <5000)   {
            b_count += 1;
        }
        else if (myDoc.SALES   <7500) {
            c_count += 1;
        }
        else if (myDoc.SALES   <10000) {
            d_count += 1;
        }
        else {
            e_count += 1;
        }       
    }
    );
   
print("a_count="+a_count)
print("b_count="+b_count)
print("c_count="+c_count)
print("d_count="+d_count)
print("e_count="+e_count)
这个需求按条件分段分组,mongodb 没有提供对应的 api,实现起来有点繁琐,上面的程序是其中实现的一个例子参考,当然也可以写成其它实现形式。下面看看集算器脚本的实现。

SPL脚本:
5
脚本说明:
       A1:定义 SALES 分组区间。
       A2:连接 mongodb 数据库。
       A3:获取 sales 表中的数据。
       A4:根据 SALES 区间分组统计员工数。其中函数 pseg()表示返回成员在序列中的区段序号,int() 表示转换成整数。
       A5:关闭数据库连接。

     Mongodb脚本与 SPL 脚本都实现了预期的结果,但函数pseg 的使用让 SPL 脚本精简了不少。

  1. 多字段分组统计
    统计分类项下的总数及各子项数。下面统计按 addr 分类的 book 的数量以及其下不同 book 类型的数量。

6
Mongo脚本
db.books.aggregate([
    {   "$group": {
      "_id": {
     
"addr": "$addr",
  "book": "$book"
},
"bookCount": {"$sum": 1}
    }},
    {   "$group": {
  "_id": "$_id.addr",
"books": {
              "$push": {
                  "book": "$_id.book",
                  "count": "$bookCount"
            },
        },
          "count": {"$sum": "$bookCount"}
    }},
    {"$sort":   { "count": -1} },
    {   "$project": {
          "books": {"$slice": [ "$books", 2] },
          "count": 1
    }}
]).pretty()
先按 addr,book 分组统计 book 数,再按 addr 分组统计 book 数,调整显示顺序。

SPL脚本 (books.dfx):
8
脚本说明:
        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 在实现分组统计方面能简化操作,降低难度,从而有效地帮助我们解决问题。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
MongoDB 5.0新特性概览
MongoDB 5.0标志着一个新的发布周期的到来,以更快地交付新特性给到用户。版本化API与在线重新分片相结合,使用户不必担心未来的数据库升级以及业务变化问题;本地原生时间序列数据平台也使MongoDB能支持更广泛的工作负载和业务场景;新的MongoDB Shell能够提升用户体验等均为MongoDB 5.0的功能。本文主要介绍MongoDB 5.0的新特性。
261 0
MongoDB 5.0新特性概览
MongoDB 5.0标志着一个新的发布周期的到来,以更快地交付新特性给到用户。版本化API与在线重新分片相结合,使用户不必担心未来的数据库升级以及业务变化问题;本地原生时间序列数据平台也使MongoDB能支持更广泛的工作负载和业务场景;新的MongoDB Shell能够提升用户体验等均为MongoDB 5.0的功能。本文主要介绍MongoDB 5.0的新特性。
445 0
快速体验mongoDB分片
随着大数据海量数据的不断涌现,分布式,横向扩展是系统扩展的重要方式之一。基于文档的NoSQL领头羊mongoDB正是这样一个分布式系统,通过分片集群将所有数据分成数据段,并将每个数据段写入不同的节点。
1052 0
mongodb的读写分离
<p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; font-family:Arial; font-size:14px; line-height:26px"> 转自:<a target="_blank" href="http://blog.csdn.net/sd0902/art
3545 0
+关注
85
文章
5
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载