MongoDB aggregate 入门
本文可能随着 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)