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 的用法:

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

按照时间进行数量统计

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

{
    "_id" : ObjectId("58f03cfc0cf5e771ec7048f3"),
    "data" : [ 
        {
            "_id" : ObjectId("58f03d460cf5e771ec7048f4"),
            "title" : "你好",
            "createdAt" : ISODate("2017-04-14T03:08:54.552Z")
        }, 
        {
            "version" : "1",
            "_id" : ObjectId("58f03d540cf5e771ec7048f5"),
            "title" : "你好",
            "createdAt" : ISODate("2017-04-14T03:09:08.114Z")
        }, 
        {
            "_id" : ObjectId("58f03d620cf5e771ec7048f6"),
            "title" : "你好",
            "createdAt" : ISODate("2017-04-14T03:09:22.567Z")
        }
    ],
    "__v" : 0
}

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

db.getCollection('releases').aggregate([
  { $unwind: "$data" }, 
  { $group: {
    _id: { 
        date: { 
            $dateToString: { format: "%Y%m%d", date: "$data.createdAt" }
         }
      }, count: { $sum: 1 }
    }
  }
])

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

如果您觉得文章不错,可以通过赞助支持我

标签: 知识, 代码段, 语法, mongodb

添加新评论