有很多时候大量日志类流水的数据存储到mongodb或者elasticsearch中,既然是数据肯定要去分析统计出我们需要的数据才是有用的数据,不然跟咸鱼没有什么区别。下面来讲讲如何运用mongodb的聚合函数(aggregate)完成sql语句中group by常规数据统计,以及常规数据查询。
MongoDB中聚合(aggregate)主要用于统计数据(比如统计平均值(mongodb分组查询语法 mongodb分组统计_JAVAsum) ,最大最小(mongodb分组查询语法 mongodb分组统计_JAVA_02max)等分组函数),并view计算后的统计结果。由于方便学习下面语句中省略的表达式我都写出来。


aggregate() 方法的使用

如何应用这个方法,首先我们还得了解方法的主要层级关系,我列出了一个图如下:

mongodb分组查询语法 mongodb分组统计_mongodb分组查询语法_03

1、mongodb分组查询语法 mongodb分组统计_字段_04match 条件关系定义一个mongodb分组查询语法 mongodb分组统计_mongodb分组查询语法_05and(或条件可以用$or)后面跟三个条件( name,addTime, money) 组成的数组。具体语句如下图:

mongodb分组查询语法 mongodb分组统计_字段_06


上图可以看出时间是从16点开始,为什么呢,因为我们使用的时间跟mongodb里面的时间早了8个小时,时区不一样,统计的时候要提前8个小时统计;

2、$group 对象中有一个特点的字段就是_id ,它就是分组统计的字段集合,_id对象后面跟着的是分组统计函数统计的数据比如sum max min 等函数;
基于上面的语句我们来一个例子,根据每天进行分组统计出王小明购买金额,以及最大的一笔金额最小的一笔金额,以及产生了多少笔交易,并显示用户名称字段name;语句怎么来写?首先我还是分析一下需求;分组条件是日期精细到天类似于2019-04-01分组,首先我们获取到addtime的年月日然后进行分组统计:具体语句如下图:

mongodb分组查询语法 mongodb分组统计_字段_07

分析一下上图写法思路。1、定义mongodb分组查询语法 mongodb分组统计_mongodb分组查询语法_08project 项目,表里面的项目就是字段了;所以这个对象是展示所需的字段默认是分组里面有什么就全部展示;这个很简单来看看下面的语法就ok了。

mongodb分组查询语法 mongodb分组统计_mongoDB_09


分析一下上面语句,分组字段_id不用写自动显示的。上面语法含义相当于 maxMoney as maxMoney_new。maxMoney_new 这个字段是自定义的。

4、$sort 这个一看就是排序功能需要的,需要排序的字段跟在后面,具体语法如下:

mongodb分组查询语法 mongodb分组统计_mongoDB_10

解析:排序升序是1 ,倒序是-1;上面理解为名称升序,最大金额倒序,交易次数倒序。

5、sql语句里面有个having,在mongodb怎么来实现呢,看了上面的代码其实已经很明了。在mongodb中是没有这个语法的,但是支持多次过滤的。意思就是可以在代码后面继续加$match进行filter。

如下图:

mongodb分组查询语法 mongodb分组统计_字段_11


这个就是实现having功能,过滤出最大金额大于等于256的数据,后面还可以进行分组 过滤 排序 等等…

这里是全部代码 结尾的skip 跟limit 是分页

db.getCollection('tablename').aggregate([
  {
    $match: {
      $and: [
        {
          name: {
            $eq: ”王小明”
          }
        },
        {
          money: {
            $gte: 200,
            $lt: 300
          }
        },
        {
          addTime: {
            $gte: ISODate("2019-03-31T16:00:00Z"),
            $lt: ISODate("2019-04-11T16:00:00Z")
          }
        }
      ]
    }
  },
  {
    $group: {
      _id: {
        year: {
          $year: {
            $add: [
              "$addTime",
              28800000
            ]
          }
        },
        month: {
          $month: {
            $add: [
              "$addTime",
              28800000
            ]
          }
        },
        day: {
          $dayOfMonth: {
            $add: [
              "$addTime",
              28800000
            ]
          }
        },
        name: "$name"
      },
      maxMoney: {
        $max: "$money"
      },
      minMoney: {
        $min: "$money"
      },
      tradeCount: {
        $sum: 1
      }
    }
  },
  {
    $project: {
      maxMoney_new: '$maxMoney',
      minMoney_new: "$minMoney",
      tradeCount_new: "$tradeCount"
    }
  },
  {
    $sort: {
      name: 1,
      maxMoney: -1,
      tradeCount: -1,
      
    }
  },
  {
    $match: {
      maxMoney_new: {
        "$gte": 256
      }
    }
  },
  {
    $skip: 0
  },
  {
    $limit: 10
  }
],
{
  "allowDiskUse": true
});

总结:mongoDB的使用语句记住JSON格式以及语法层级关系,写起来得心应手,有什么疑问和探讨的欢迎在下面留言。再说一句 allowDiskUse 这个是启用磁盘缓存,防止返回数据过多报错。