聚合操作对查询到的记录分组,然后对每组记录进行统计计算,返回统计结果。在SQL中,count(*)
配合group by
可以统计每组记录的条数,就相当于MongoDB中的聚合sum。
aggregate() 方法
MongoDB中,聚合操作可以使用aggregate()
方法。
语法
aggregate()
方法的基本语法如下:
db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
例子
在qikegu集合中有以下数据:
> db.qikegu.find().pretty()
{
"_id" : ObjectId("5cf7b91d9ad87fde6fd23a06"),
"title" : "MongoDB 概述",
"description" : "MongoDB是一个以文档为中心的NOSQL数据库",
"by" : "qikegu.com",
"url" : "https://www.qikegu.com",
"tags" : [
"mongodb",
"database",
"NoSQL"
],
"likes" : 88
}
{
"_id" : ObjectId("5cf7b91d9ad87fde6fd23a07"),
"title" : "MongoDB 优势",
"description" : "MongoDB相对于RDBMS的优势",
"by" : "qikegu.com",
"url" : "https://www.qikegu.com",
"tags" : [
"mongodb",
"database",
"NoSQL"
],
"likes" : 89,
"comments" : [
{
"user" : "user1",
"message" : "My first comment",
"dateCreated" : ISODate("2018-12-09T18:35:00Z"),
"like" : 0
}
]
}
现在,要统计qikegu.com写了多少个教程,可以使用aggregate()
方法:
> db.qikegu.aggregate([{$group : {_id : "$by", num_tutorial : {$sum : 1}}}])
{ "_id" : "qikegu.com", "num_tutorial" : 2 }
上面的例子,等价的SQL查询是
select `by`, count(*) from qikegu group by `by`
在上面的例子中,按照字段by
对结果进行分组,并统计分组中记录条数。下面是聚合表达式的列表:
表达式 | 描述 | 例子 |
---|---|---|
$sum | 汇总集合中文档的字段值。 | db.qikegu.aggregate([{group : {_id : “by”, num_tutorial : {sum : “likes”}}}]) |
$avg | 计算集合中,所有文档中所有给定值的平均值。 | db.qikegu.aggregate([{group : {_id : “by”, num_tutorial : {avg : “likes”}}}]) |
$min | 获取集合中,文档字段的最小值 | db.qikegu.aggregate([{group : {_id : “by”, num_tutorial : {min : “likes”}}}]) |
$max | 获取集合中,文档字段的最大值 | db.qikegu.aggregate([{group : {_id : “by”, num_tutorial : {max : “likes”}}}]) |
$push | 将全部文档的某个字段值作为数组插入到结果中。 | db.qikegu.aggregate([{group : {_id : “by”, url : {push: “url”}}}]) |
$addToSet | 将全部文档的某个字段值作为数组插入到结果中,但字段值不重复。 | db.qikegu.aggregate([{group : {_id : “by”, url : {addToSet : “url”}}}]) |
$first | 获取分组中的最后一个文档,通常,文档是有序的这个操作才有意义。 | db.qikegu.aggregate([{group : {_id : “by”, first_url : {first : “url”}}}]) |
$last | 获取分组中的首个文档,通常,文档是有序的这个操作才有意义。 | db.qikegu.aggregate([{group : {_id : “by”, last_url : {last : “url”}}}]) |
管道
在UNIX命令中,管道可以让某些命令的输出,作为另一个命令的输入,以此类推。MongoDB的聚合框架中也支持相同的概念,某些操作阶段输出一组文档,这些文档可以作为另一组操作阶段的输入,以此类推。
下面是聚合框架的可能阶段,可以把这些阶段串联组合起来:
- $project — 用于从集合中选择某些字段。
- $match — 这是一个过滤操作,过滤文档。
- $group — 这是如上所述的实际聚合。
- $sort — 对文档进行排序。
- $skip – 结果偏移量,类似mysql中的offset。
- $limit — 限定结果数量。
- $unwind – 用于展开使用数组的文档。例如:
{ "_id" : 1, "item" : "ABC1", sizes: [ "S", "M", "L"] }
会被展开成为:
{ "_id" : 1, "item" : "ABC1", "sizes" : "S" } { "_id" : 1, "item" : "ABC1", "sizes" : "M" } { "_id" : 1, "item" : "ABC1", "sizes" : "L" }