MongoDB
聚合 aggregate
聚合操作就是把源数据集放到管道里加以处理得到统计后的结果
db.collectionName.aggregate([{ 管道 :{ 表达式 }}])
常用管道:
$group
:给集合的文档分组,可用于统计结果,相当于GROUP BY$match
:过滤数据,只输出符合条件的文档,相当于HAVING$project
:选出来原始文档中的某些字段$sort
:将输入排序后输出$limit
$skip
$unwind
:将数组类型的字段进行拆分
常用表达式:
$sum
:计算综合,$sum:1
和count一样表示计数$avg
,$min
,$max
等等类似$push
:在结果文档中插入值到一个数组当中去$first / $last
:获取第一个/最后一个文档数据
分组 $group
:
counter:累计器
db.hi.aggregate([{
$group: {
_id: "$gender", // 基于谁分组 ,①先把gender一样的分组(分出男女两组,每组若干个文档)
//_id:null // 整个集合分为一组
counter: { // 结果字段的统计方式(计数、求和、求平均数) ,②再分别在每个组内统计:
$sum: 1 // $sum: 1 就是 sql里的count(*) ,计数每组文档数量
//$avg:"$age", // 该组所有成员的某个键对应的平均值(该组年龄的平均值)
//$last:"$age" // 该组所有成员某个键对应的最后一个值(该组年龄的最后一个值,排序后有意义)
//$push:"$age" // 该组所有成员某个键对应的值插入到一个数组里(该组所有年龄插入数组)
//$push:"$$ROOT" // 该组所有成员的完整文档插入到一个数组里
}
}
}]
过滤 $match
:
和find方法一样,find是不能进行统计的,$match可以统计
管道内先写match后写group,
db.collection.aggregate([{
$match: {
age: {
$gt: 20 // 查询到年龄比20大的文档
}
}
}])
投影 $project
:
把结果集当中的一部分拿出来显示:
db.collection.aggregate([
{ $match :{ age :{ $gt:20}}},
{ $group :{ _id:"$gender",counter :{ $sum:1}}},
{ $project :{ _id:0, counter : 1}}, // _id就是上面的gender字段,0代表不显示该字段,1代表显示该字段
])
排序 $sort
:
db.collection.aggregate([
{ $match :{ age:{ $gt : 20 }}},
{ $group :{ _id:"gender",counter :{ $sum:1 }}},
{ $project :{ _id:0, counter :1 }}, // 0代表不显示该字段,1代表显示该字段
{ $sort :{ counter : 1 }}, // 把指定字段按 :1 顺序排列 -1 倒序排列
])
跳过$skip
范围$limit
:
db.collection.aggregate([
{ $match :{ age :{ $gt : 20 }}},
{ $group :{ _id:"gender", counter :{ $sum : 1 }}},
{ $project :{ _id:0 , counter : 1 }},
{ $sort :{ counter : 1 }},
{ $skip : 1 }, //有顺序规定
{ $limit : 1 }
])
拆分数组 $unwind
:
逆group操作,把数组拆分
{
field1: value1,
field2: [item1, item2]
}
拆分成:
{
field1: value1,
field2: item1
}
{
field1: value1,
field2: item2
}
db.collection.aggregate([
{
$unwind : {
path : "$size", // 需要被拆分的数组值的对应字段名
preserveNullAndEmptyArrays : true // 防止非数组数据丢失
}
}
])
实例:
聚合数据的反拆:
db.collection.aggregate([
{
$group:
{
_id: "gender",
counter: { $sum: 1 },
docs: { $push: "$$ROOT" }
}
},
{
$project:
{
_id: 0, counter: 1, docs: 1
}
},
{
$unwind : {
path : "$docs", // 这样就拿到了所有管道操作以后的源数据集
preserveNullAndEmptyArrays : true
}
}
])