CodeSky 代码之空

随手记录自己的学习过程

MongoDB aggregate 入门

2017-04-17 22:12分类: SQL评论: 0

本文可能随着 MongoDB 使用技能的增长而更新,因为 aggregate 可以做的事情太多啦。

在 MongoDB 中,最强大的工具无异于 aggregate,aggregate 接受一个数组,数组的每一项都是管道(pipeline)对象。

管道的概念我们在 Linux 中也遇到过,可以把前面的返回值作为后者的输入值操作。

MongoDB 为我们提供了一系列管道聚集阶段(Pipeline Aggregation Stages):

  • $project:增加或删除或重命名(其实就是重新组织)document 的 fields。
  • $match:根据筛选条件匹配过滤
  • $limit:限制输出数量
  • $skip:跳过指定个数的 document
  • $unwind:解构 document 中的 Array field,变为若干个 item type field 对应的 documents
  • $group:聚类
  • $sort:排序
  • $lookup:相当于 left outer join,在 3.2 版本才加入了这一设定。(在 mongoose 中很早就可以使用 populate 来实现 collection 之间的关联,不过和外键概念还是有差别的)

其他的暂时还没用到过,就不多做介绍了。

在下面我们举出一些用到的应用场景:

rename _id

这种用法当然是大材小用,但是可以很方便的说明 $project 的用法:

1db.getCollection('releases').aggregate([{ $project: { id: "$_id", _id: 0 }}])
2

按照时间进行数量统计

在工作中有这样一个需求,我需要根据时间聚类并且 count,在 MongoDB 中的存储结构类似于:

1{
2    "_id" : ObjectId("58f03cfc0cf5e771ec7048f3"),
3    "data" : [ 
4        {
5            "_id" : ObjectId("58f03d460cf5e771ec7048f4"),
6            "title" : "你好",
7            "createdAt" : ISODate("2017-04-14T03:08:54.552Z")
8        }, 
9        {
10            "version" : "1",
11            "_id" : ObjectId("58f03d540cf5e771ec7048f5"),
12            "title" : "你好",
13            "createdAt" : ISODate("2017-04-14T03:09:08.114Z")
14        }, 
15        {
16            "_id" : ObjectId("58f03d620cf5e771ec7048f6"),
17            "title" : "你好",
18            "createdAt" : ISODate("2017-04-14T03:09:22.567Z")
19        }
20    ],
21    "__v" : 0
22}
23

首先我们将 document 中的 array 解构,这样才可以统计,之后根据日期聚类,MongoDB 针对 Date 类型有一系列的处理操作符,之后在使用 $sum 运算符统计即可:

1db.getCollection('releases').aggregate([
2  { $unwind: "$data" }, 
3  { $group: {
4    _id: { 
5        date: { 
6            $dateToString: { format: "%Y%m%d", date: "$data.createdAt" }
7         }
8      }, count: { $sum: 1 }
9    }
10  }
11])
12

如果有筛选的需要,我们可以在中间加上 $match。如果发现自己写的语句报错了,可以很方便的删除管道中的一个阶段,一阶段一阶段的进行调试。

评论 (0)