MongoDB聚合和管道
1、聚合
聚合(aggregate)是基于数据处理的聚合管道,每个文档通过一个由多个阶段(stage)组成的管道,可以对每个阶段的管道进行分组、过滤等功能。
语法格式:db.集合名称.aggregate({管道:{表达式}})
2、常用管道
⽂档处理完毕后, 通过管道进⾏下⼀次处理
常用管道 | |
---|---|
$group | 将集合中的⽂档分组, 可⽤于统计结果 |
$match | 过滤数据, 只输出符合条件的⽂档 |
$project | 修改输⼊⽂档的结构, 如重命名、 增加、 删除字段、 创建计算结果 |
$sort | 将输⼊⽂档排序后输出 |
$limit | 限制聚合管道返回的⽂档数 |
$skip | 跳过指定数量的⽂档, 并返回余下的⽂档 |
$unwind | 将数组类型的字段进⾏拆分 |
3、表达式
处理输⼊⽂档并输出
语法格式:表达式:'$列名'
常⽤表达式 | |
---|---|
$sum | 计算总和, $sum:1 表示以⼀倍计数 |
$avg | 计算平均值 |
$min | 获取最⼩值 |
$max | 获取最⼤值 |
$push | 在结果⽂档中插⼊值到⼀个数组中 |
$first | 根据资源⽂档的排序获取第⼀个⽂档数据 |
$last | 根据资源⽂档的排序获取最后⼀个⽂档数据 |
4、$group
将集合中的文档分组,可用于统计结果
_id
表示分组的依据,使用某个字段的格式为’$字段
’
//示例
// 返回sex有哪些值
> db.test.aggregate(
{$group:{
_id:"$sex"
}
}
)
//统计男生、女生分别的总人数
> db.test.aggregate(
{$group:
{
_id:"$sex",
count:{$sum:1}
}
}
)
//统计男、女分别的平均年龄
> db.test003.aggregate(
{$group:
{
_id:"$sex",
count:{$sum:1},
avg_age:{$avg:"$age"}
}
}
)
注意:
_id:null
:将集合中所有文档分为一组
//示例--求总人数、平均年龄
> db.test.aggregate(
{$group:
{
_id:null,
count:{$sum:1},
avg_age:{$avg:"$age"}
}
}
)
总结:
-
$group
对应的字典中有几个键,结果中就有几个键 -
分组依据需要放到
_ id
后面 -
取不同的字段的值需要使用
$
,如:$hometown
、$age
、$sex
-
取字典嵌套的字典中值的时候
$_id.字段名
-
同时取多个键进行分组:
{$group:{_id:{字段名1:"$字段名1",字段名2:"字段名2"}}}
;输出结果:{_id:{字段名1:"",字段名2:""}
5、$project
修改输入文档的结构,如重命名、增加、删除字段、创建计算结果;简单来说就是修改输入输出的值
//示例
//查询姓名、年龄
> db.test.aggregate({$project:{_id:0, name:1, age:1}})
//查询男、女人数,输出人数
> db.test.aggregate(
{$group:{_id:'$sex', count:{$sum:1}}},
{$project:{_id:0, count:1}}
)
6、$match
用于过滤数据,只输出符合条件的文档
-
使用MongoDB的标准查询操作
-
match
是管道命令,能将结果交给后一个管道,但是find
不可以
//查询年龄大于20的
> db.test.aggregate(
{$match:{age:{$gt:20}}}
)
//查询年龄大于等于18的男生、女生人数
> db.test.aggregate(
{$match:{age:{$gte:18}}},
{$group:{_id:'$sex',count:{$sum:1}}}
)
7、$sort
将输入文档排序后输出
//查询信息,按年龄升序
> db.test.aggregate({$sort:{age:1}})
//查询男生、女生人数,按人数降序
> db.test.aggregate(
{$group:{_id:'$sex',count:{$sum:1}}},
{$sort:{count:-1}}
)
8、$limit
限制聚合管道返回的文档数量
//查询2条信息
> db.test.aggregate({$limit:2})
9、$skip
跳过指定数量的文档,并返回余下的文档
//查询从第3条开始的信息
> db.test.aggregate({$skip:2})
//跳过前2个文档,然后返回接下来的1个文档
> db.test.aggregate(
{$skip:2},
{$limit:1}
)
注意:两者都用时,先写skip, 再写limit。
10、$unwind
将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值
语法格式:db. 集合名称.aggregate({$unwind:'$字段名称’})
> db.test.insert({_id:1, item:'t-shirt', size:['S','M','L']})
WriteResult({ "nInserted" : 1 })
> db.test.aggregate({$unwind: '$size'})
{ "_id" : 1, "item" : "t-shirt", "size" : "S" }
{ "_id" : 1, "item" : "t-shirt", "size" : "M" }
{ "_id" : 1, "item" : "t-shirt", "size" : "L" }
- 属性
preserveNullAndEmptyArrays
值为true表示保留属性值为空的⽂档;值为false表示丢弃属性值为空的⽂档
db.test.aggregate({
$unwind:{
path:'$字段名称',
preserveNullAndEmptyArrays:<boolean>
}
})