MongoDB聚合是什么?
- MongoDB中的聚合操作将多个文档中的值组合在一起,并可对分组数据执行各种操作,以返回单个结果。
个人理解:
聚合操作中主要使用到了“管道”的概念。管道的入口是一个集合,管道的出口是你所需要的数据。这个管道中间是有一个个功能节点组成的,可以类比实际生活中一节一节的管道,每个功能节点都会对上一个节点的结果进行一定的操作,如过滤掉某些文档、对文档进行排序等等。相当于把对某个集合的一系列操作使用一个指令完成,比一个指令一个指令操作的优势在于Mongo会在上一个操作结束之后将结果保留在内存中直接进行下一个操作,会更加节省资源速度会更快
常用管道命令
字段名 | 解释 |
---|---|
$match | 过滤操作,筛选符合条件文档 作为下一阶段的输。注意:1. $match尽量出现在管道的前面,这样可以提早过滤文档,加快聚合速度也可以使用索引来加快查询。 |
$count | 返回包含输入到stage的文档的计数 |
$limit | 限制经过管道的文档数量 , $limit的参数只能是一个正整数 |
$skip | 从待操作集合开始的位置跳过文档的数目 $skip参数也只能为一个正整数 |
$group | 将文档依据指定字段的不同值进行分组 。 |
$sort | 对文档按照指定字段排序 ,1表示正序,-1表示倒序,注意:1.如果将$sort放到管道前面的话可以利用索引,提高效率 |
$project | 通过重命名,添加或删除字段重塑文档 。 |
$unwind | 将数组分解为单个的元素,并与文档的其余部分一同返回 注意:1.如果$unwind目标字段不存在,则整个文档都会被忽略过滤掉 2.如果$unwind目标字段不是一个数组,则会报错 3.如果$unwind目标字段数组为空,则该文档也会被忽略过滤掉 |
$out | 用户将聚合的结果输出到指定的集合 ,如果要使用$out则必须在整个管道操作的最后阶段 如果指定的集合尚不存在,$out 操作会在当前数据库中创建一个新的集合。集合不是可见的直到聚合完成。如果聚合失败,MongoDB 不会创建集合。 如果集合指定的$out 操作已经存在,$out 阶段以原子方式以新的结果集合替换现有集合的,$out 操作不会更改任何存在于以前的集合的索引 |
常用表达式
名称 | 描述 |
---|---|
$avg | 计算均值 |
$first | 返回每组第一个文档 ,如果有排序,按照排序,如果没有按照默认的存储的顺序的 |
$last | 返回每组最后一个文档 ,如果有排序,按照排序,如果没有按照默认的存储的顺序的 |
$max | 根据分组,获取集合中所有文档对应值得最大值 。 |
$min | 根据分组,获取集合中所有文档对应值得最小值 。 |
$push | 将指定的表达式的值添加到一个数组中 (不会去重直接添加 )。 |
$addToSet | 将表达式的值添加到一个集合中(会自动去重 )。 |
$sum | 计算总和 |
管道命令之$group
按照某个字段进行分组
- $group是所有聚合命令中用的最多的一个命令,用来将集合中的文档分组,可用于统计结果
(1)按照某个字段进行分组
使用示例如下:
db.orders.aggregate(
[{$group:
{
_id:"$gender",
counter:{$sum:1}
}
}]
)
注意点
:
- db.db_name.aggregate是语法,所有的管道命令都需要写在其中
- _id 表示分组的依据,按照哪个字段进行分组,使用$gender表示选择这个字段进行分组
- $sum:1 表示把每条数据作为1进行统计,统计的是该分组下面数据的条数
(2)group by null
当我们需要统计整个文档的时候,$group 的另一种用途就是把整个文档分为一组进行统计
使用实例如下:
db.orders.aggregate(
[{$group:
{
_id:null,
counter:{$sum:1}
}
}]
)
注意点
:
_id:null 表示不指定分组的字段,即统计整个文档,此时获取的counter表示整个文档的个数
管道命令之$match
$match用于进行数据的过滤,是在能够在聚合操作中使用的命令,和find区别在于$match 操作可以把结果交给下一个管道处理,而find不行
使用示例如下:
查询年龄大于20的学生
db.stu.aggregate(
[{$match:{age:{$gt:20}}]
)
管道命令之$project
$project用于修改文档的输入输出结构,例如重命名,增加,删除字段
使用示例如下:
(1)查询学生的cust_id、price,仅输出cust_id、price
db.orders.aggregate( [
{ $project :
{ _id: 0, cust_id : 1 , price : 1
}
} ] )
(2)设置别名
db.orders.aggregate( [
{
$project :
{ _id: 0, cust_id : 1 , price : 1, qty: "$status"
}
} ] )
(3)在投影的过程中是可以进行四则远算的:加法($add)、减法($subtract)、乘法($multipy)、除法($divide)、求模($mod)
示例:对 quantity 乘以 2(使用 $multiply 操作)
db.orders.aggregate([{ $project :
{ _id: 0, cust_id : 1 , price: {"priceaa" : { "$multiply" : ["$price", 2] }} }
}]);
管道命令之$skip 和 $limit
使用示例如下:
查询1条学生信息
db.stu.aggregate(
[{$limit:1}]
)
跳过第一条信息,查询第2条开始的信息
db.stu.aggregate(
[{$skip:1}]
)