您的位置:首页 > 数据库 > Mongodb

06-MongoDB聚合aggregate

2018-03-06 14:09 323 查看

06-MongoDB聚合aggregate

什么是聚合

聚合(aggregate)主要用于计算数据,类似sql中的sum()、avg()

语法

db.集合名称.aggregate([{管道:{表达式}}])


管道

当文档处理完毕后,通过管道可以进一步处理

序号管道命令类型
1$group将集合中的文档分组,可用于统计结果
2$match过滤数据,只输出符合条件的文档
3$project修改输入文档的结构,如重命名、增加、删除字段、创建计算结果
4$sort将输入文档排序后输出
5$limit限制聚合管道返回的文档数
6$skip跳过指定数量的文档,并返回余下的文档
7$unwind将数组类型的字段进行拆分

表达式

表达式:'$列名'


序号表达式类型
1sum|计算总和,sum|计算总和,sum:1同count表示计数
2$avg计算平均值
3$min获取最小值
4$max获取最大值
5$push在结果文档中插入值到一个数组中
6$first根据资源文档的排序获取第一个文档数据
7$last根据资源文档的排序获取最后一个文档数据

$Group

将集合中的文档进行分组,用于统计结果,使用某个字段进行分组的格式为‘$Group’

先查出所有学生

/* 1 */
{
"_id" : ObjectId("5a98f8ddf4a43a13865dc78b"),
"name" : "Rps",
"gender" : 1,
"age" : 22
}

/* 2 */
{
"_id" : "20160101",
"name" : "JackMa",
"gender" : 0.0,
"age" : 20
}

/* 3 */
{
"_id" : ObjectId("5a98fd85f4a43a13865dc78c"),
"name" : "hr",
"gender" : 1,
"age" : 42
}

/* 4 */
{
"_id" : ObjectId("5a9e25c4e22f7535dd66aab3"),
"name" : "EricChen",
"gender" : 0.0,
"age" : 20
}

/* 5 */
{
"_id" : ObjectId("5a9e25cbe22f7535dd66aab4"),
"name" : "Make",
"gender" : 1,
"age" : 23
}


根据性别对学生进行分组

db.stu.aggregate([{
$group:{
_id:'$gender',
counter:{$sum:1}
}
}])

/* 1 */
{
"_id" : 1.0,
"counter" : 2.0
}

/* 2 */
{
"_id" : 0.0,
"counter" : 3.0
}


求出学生总人数和平均年龄

db.stu.aggregate([{
$group:{
_id: null,
counter:{$sum:1},
aveAge:{$avg:'$age'}
}
}])

/* 1 */
{
"_id" : null,
"counter" : 5.0,
"aveAge" : 20.0
}


透视数据:

统计学生性别及学生姓名

db.stu.aggregate([
{$group:
{
_id:'$gender',
name:{$push:'$name'}
}
}
])

/* 1 */
{
"_id" : 0.0,
"name" : [
"JackMa",
"EricChen"
]
}

/* 2 */
{
"_id" : 1,
"name" : [
"Rps",
"hr",
"Make"
]
}


使用$$ROOT可以将文档内容加入到结果集的数组中,代码如下

db.stu.aggregate([
{$group:
{
_id:'$gender',
name:{$push:'$$ROOT'}
}
}
])
/* 1 */
{
"_id" : 0.0,
"name" : [
{
"_id" : "20160101",
"name" : "JackMa",
"gender" : 0.0,
"age" : 20
},
{
"_id" : ObjectId("5a9e25c4e22f7535dd66aab3"),
"name" : "EricChen",
"gender" : 0.0,
"age" : 20
}
]
}

/* 2 */
{
"_id" : 1,
"name" : [
{
"_id" : ObjectId("5a98f8ddf4a43a13865dc78b"),
"name" : "Rps",
"gender" : 1,
"age" : 22
},
{
"_id" : ObjectId("5a98fd85f4a43a13865dc78c"),
"name" : "hr",
"gender" : 1,
"age" : 42
},
{
"_id" : ObjectId("5a9e25cbe22f7535dd66aab4"),
"name" : "Make",
"gender" : 1,
"age" : 23
}
]
}


$match

用于过滤数据,只输出符合条件的文档

查询年龄大于20的学生:

db.stu.aggregate([{
$match:{
age:{
$gt:20
}
}
}])

/* 1 */
{
"_id" : ObjectId("5a98f8ddf4a43a13865dc78b"),
"name" : "Rps",
"gender" : 1,
"age" : 22
}

/* 2 */
{
"_id" : ObjectId("5a98fd85f4a43a13865dc78c"),
"name" : "hr",
"gender" : 1,
"age" : 42
}

/* 3 */
{
"_id" : ObjectId("5a9e25cbe22f7535dd66aab4"),
"name" : "Make",
"gender" : 1,
"age" : 23
}


$project

修改输入文档的结构,如重命名、增加、删除字段、创建计算结果

查询学生的姓名、年龄

db.stu.aggregate([{
$project:{
_id:0,
name:1,
age:1
}
}])

/* 1 */
{
"name" : "Rps",
"age" : 22
}

/* 2 */
{
"name" : "JackMa",
"age" : 20
}

/* 3 */
{
"name" : "hr",
"age" : 42
}

/* 4 */
{
"name" : "EricChen",
"age" : 20
}

/* 5 */
{
"name" : "Make",
"age" : 23
}


查询男生、女生人数,输出人数

db.stu.aggregate([
{$group:{_id:'$gender',counter:{$sum:1}}},
{$project:{_id:0,counter:1}}
])
/* 1 */
{
"counter" : 2.0
}

/* 2 */
{
"counter" : 3.0
}


$sort

将输入文档排序后输出

查询学生信息,按年龄升序:

db.stu.aggregate([
{$sort:{age:1}}
])
/* 1 */
{
"_id" : "20160101",
"name" : "JackMa",
"gender" : 0.0,
"age" : 20
}

/* 2 */
{
"_id" : ObjectId("5a9e25c4e22f7535dd66aab3"),
"name" : "EricChen",
"gender" : 0.0,
"age" : 20
}

/* 3 */
{
"_id" : ObjectId("5a98f8ddf4a43a13865dc78b"),
"name" : "Rps",
"gender" : 1,
"age" : 22
}

/* 4 */
{
"_id" : ObjectId("5a9e25cbe22f7535dd66aab4"),
"name" : "Make",
"gender" : 1,
"age" : 23
}

/* 5 */
{
"_id" : ObjectId("5a98fd85f4a43a13865dc78c"),
"name" : "hr",
"gender" : 1,
"age" : 42
}


例2:查询男生、女生人数,按人数降序

db.stu.aggregate([
{$group:{_id:'$gender',counter:{$sum:1}}},
{$sort:{counter:-1}}
])
/* 1 */
{
"_id" : 1,
"counter" : 3.0
}

/* 2 */
{
"_id" : 0.0,
"counter" : 2.0
}


$limit

限制聚合管道返回的文档数

db.stu.aggregate([{$limit:2}])


$skip

跳过指定数量的文档,并返回余下的文档

例2:查询从第3条开始的学生信息

db.stu.aggregate([{$skip:2}])


例3:统计男生、女生人数,按人数升序,取第二条数据

db.stu.aggregate([
{$group:{_id:'$gender',counter:{$sum:1}}},
{$sort:{counter:1}},
{$skip:1},
{$limit:1}
])


注意顺序:先写skip,再写limit$unwind

$unwind

将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值

语法1:对某字段值进行拆分

db.集合名称.aggregate([{$unwind:'$字段名称'}])


db.stu.aggregate([{$unwind:'$size'}])
/* 1 */
{
"_id" : 1.0,
"item" : "num",
"size" : "S"
}

/* 2 */
{
"_id" : 1.0,
"item" : "num",
"size" : "M"
}

/* 3 */
{
"_id" : 1.0,
"item" : "num",
"size" : "L"
}


语法2:对某字段进行拆分同事处理空数组,非数组,无字段,null情况

db.inventory.aggregate([{
$unwind:{
path:'$字段名称',
preserveNullAndEmptyArrays:<boolean>#防止数据丢失
}
}])


当使用语法1时:发现对于空数组、无字段、null的文档,都被丢弃了

db.my.insert([
{ "_id" : 1, "item" : "a", "size": [ "S", "M", "L"] },
{ "_id" : 2, "item" : "b", "size" : [ ] },
{ "_id" : 3, "item" : "c", "size": "M" },
{ "_id" : 4, "item" : "d" },
{ "_id" : 5, "item" : "e", "size" : null }
])

db.my.aggregate([{$unwind:'$size'}])

/* 1 */
{
"_id" : 1.0,
"item" : "a",
"size" : "S"
}

/* 2 */
{
"_id" : 1.0,
"item" : "a",
"size" : "M"
}

/* 3 */
{
"_id" : 1.0,
"item" : "a",
"size" : "L"
}

/* 4 */
{
"_id" : 3.0,
"item" : "c",
"size" : "M"
}


使用语法2:

db.my.aggregate([
{$unwind:{path:'$sizes',preserveNullAndEmptyArrays:true}}
])


/* 1 */
{
"_id" : 1.0,
"item" : "a",
"size" : [
"S",
"M",
"L"
]
}

/* 2 */
{
"_id" : 2.0,
"item" : "b",
"size" : []
}

/* 3 */
{
"_id" : 3.0,
"item" : "c",
"size" : "M"
}

/* 4 */
{
"_id" : 4.0,
"item" : "d"
}

/* 5 */
{
"_id" : 5.0,
"item" : "e",
"size" : null
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: