聚合操作
mongodb的聚合是什么
"""
聚合(aggregate)是基于数据处理的聚合管道,每个文档通过一个由多个阶段(stage)组成的管道,可以对每个阶段的管道进行分组、过滤等功能,然后经过一系列的处理,输出相应的结果。
类比:MySQL
"""
聚合操作前戏
"""
1 常用管道命令
在mongodb中,⽂档处理完毕后, 通过管道进⾏下⼀次处理 常用管道命令如下:
$group: 将集合中的⽂档分组, 可⽤于统计结果
$match: 过滤数据, 只输出符合条件的⽂档
$project: 修改输⼊输出⽂档的结构, 如重命名、 增加、 删除字段、 创建计算结果
$sort: 将输⼊⽂档排序后输出
$limit: 限制聚合管道返回的⽂档数
$skip: 跳过指定数量的⽂档, 并返回余下的⽂档
2 常用表达式
表达式:处理输⼊⽂档并输出 语法:表达式:'$列名' 常⽤表达式:
$sum: 计算总和, $sum:1 表示以⼀倍计数
$avg: 计算平均值
$min: 获取最⼩值
$max: 获取最⼤值
$push: 在结果⽂档中插⼊值到⼀个数组中
"""
$group
# 1) 按照某个字段进行分组
"""
$group: 将集合中的⽂档分组, 可⽤于统计结果
"""
db.stu.aggregate({$group:{_id:'$gender',counter:{$sum:1}}})
db.stu.aggregate({$group:{_id:null,counter:{$sum:1}}})
"""
_id 表示分组的依据,按照哪个字段进行分组,需要使用$gender表示选择这个字段进行分组
$sum:1 表示把每条数据作为1进行统计,统计的是该分组下面数据的条数
注意:_id:null 表示不指定分组的字段,即统计整个文档,此时获取的counter表示整个文档的个数
"""
# 2)数据透视
数据透视就是把所有的数据放在一块,方便查找
1.统计不同性别的学生
db.stu.aggregate({$group:{_id:null,name:{$push:"$name"}}})
# $push:在结果文档中插入值到一个数组中
db.stu.aggregate({$group:{_id:null,name:{$push:'$$ROOT'}}})
# 使用$$ROOT 可以将整个文档放入数组中 必须是大写ROOT
$match
"""
$match: 过滤数据, 只输出符合条件的⽂档
"""
1.查询年龄大于20的学生
db.stu.aggregate(
{$match:{age:{$gt:20}}}
)
2.查询年龄大于20的男女学生的人数
db.stu.aggregate(
{$match:{age:{$gt:20}}},
{$group:{_id:"$gender",counter:{$sum:1}}}
)
$project
"""
$project: 修改输⼊输出⽂档的结构, 如重命名、 增加、 删除字段、 创建计算结果
"""
1.查询学生的年龄、姓名、仅输入年龄姓名
db.stu.aggregate(
{$project:{_id:0,name:1,age:1}}
)
2.查询男女生人数,输出人数
db.stu.aggregate(
{$group:{_id:"$gender",counter:{$sum:1}}},
{$project:{_id:0,counter:1}}
)
"""
总结:$project中:0为不显示,1为显示
"""
$sort
"""
$sort: 将输⼊⽂档排序后输出
"""
1.查询学生信息,按照年龄升序
db.stu.aggregate({$sort:{age:1}})
2.查询男女人数,按照人数降序
db.stu.aggregate(
{$group:{_id:"$gender",counter:{$sum:1}}},
{$sort:{counter:-1}}
)
$skip和$limit
"""
$limit限制返回数据的条数
$skip 跳过指定的文档数,并返回剩下的文档数
同时使用时先使用skip在使用limit
"""
1.查询2条学生数据
db.stu.aggregate(
{$limit:2}
)
2.查询从第三条开始的学生信息
db.stu.aggregate(
{$skip:3}
)
3.统计男女人数,按照人数升序,返回第二条数据
db.stu.aggregate(
{$group:{_id:"$gender",counter:{$sum:1}}},
{$sort:{counter:1}},
{$skip:1},
{$limit:1}
)
索引操作
# 1) 为什么mongodb需要创建索引
1.加快查询速度
2.进行数据的去重
# 2)mongodb创建简单的索引方法
语法:db.集合名.ensureIndex({属性:1}) # 1表示升序, -1表示降序
# 3) 创建索引前后查询速度对比
插入数据:
for(i=1;i<100000;i++){db.t1.insert({name:'test'+i,age:i})}
# 创建索引前
db.t1.find({name:'test10000'})
db.t1.find({name:'test10000'}).explain('executionStats') # 显示查询操作的详细信息
# 创建索引
db.t1.ensureIndex({name:1})
# 创建索引后
db.t1.find({name:'test10000'}).explain('executionStats')
# 创建索引之后速度有了非常明显的提升
# 4)索引的查看
默认情况下_id是集合的索引 查看方式:db.t1.getIndexes()
# 5) 删除索引
db.t1.dropIndex({name:1})
# 6) 创建唯一索引
"""
创建唯一索引之后,数据库会在插入数据的时候检查创建索引域的值是否存在,
如果存在则不会插入该条数据,但是创建索引仅仅能够提高查询速度,同时降低数据库的插入速度。
"""
# 6.1)添加唯一索引的语法
db.集合名.ensureIndex({'字段名':1},{'unique':true})
# 利用唯一索引进行数据的去重,如果索引相同,则不会插入
# 6.2)建立复合索引
"""
使用场景:QQ空间说说,把qq名称作为唯一索引进行去重是不可取的,有可能发布的数据也是相同的,
这时就需要用复合索引
"""
# 建立复合索引的语法:
db.collection_name.ensureIndex({字段1:1,字段2:1})
# 注意:谨慎使用,使用不当会降低效率