MongoDB-聚合查询
聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。
语法:db.集合名称.aggergate({管道:{表达式}})
常用的管道命令:
-$group: 将集合中的文档分组,可以统计结果
-$match: 过滤数据,只输出符合条件的文档
-$project: 修改输入文档的结构,如重命名、增加、删除字段、创建计算结果
-$sort: 将输入文档排序后输出
-$limit: 限制聚合管道返回的文档数
-$skip: 跳过指定数量的文档,并返回余下的文档
常用表达式:
-$sum: 计算总和,$sum:1 表示以一倍计数
-$avg: 计算平均值
-$min: 获取最小值
-$max: 获取最大值
-$push: 在结果文档中插入值到一个数组中
管道命令之$group:
按照某个字段分组:
示例1:根据姓名分组,并算出每组的个数。
db.nor_col.aggregate({$group:{_id:"$name",counter:{$sum:1}}}) 结果: { "_id" : null, "counter" : 2 } { "_id" : "liu2", "counter" : 1 } { "_id" : "liu", "counter" : 1 } { "_id" : "yang", "counter" : 1 } { "_id" : "wang", "counter" : 3 } { "_id" : "孙权", "counter" : 4 } { "_id" : "周瑜", "counter" : 1 } { "_id" : "孙策", "counter" : 1 } 说明: _id 表示分组的依据,按照哪个字段进行分组,需要使用$name表示选择这个字段进行分组 $sum:1 表示把每条数据作为1进行统计,统计的是该分组下面数据的条数 counter只是个字段名称,可以随意换的,比如你换成num,那么结果就是num
示例2: 根据姓名分组,计算出每组的个数,然后再计算出每组年龄的和
db.nor_col.aggregate({$group:{_id:"$name",counter:{$sum:1},age_sum:{$sum:"$age"}}}) 结果: { "_id" : "liu2", "counter" : 1, "age_sum" : 21 } { "_id" : "liu", "counter" : 1, "age_sum" : 21 } { "_id" : "yang", "counter" : 1, "age_sum" : 21 } { "_id" : "wang", "counter" : 3, "age_sum" : 63 } { "_id" : "孙权", "counter" : 4, "age_sum" : 84 } { "_id" : "周瑜", "counter" : 1, "age_sum" : 21 } { "_id" : "孙策", "counter" : 1, "age_sum" : 21 }
示例3: 根据姓名分组,根据num字段分组,然后看看每个组的名字是谁
db.nor_col.aggregate({$group:{_id:"$num",name_list:{$push:"$name"}}}) 结果: { "_id" : 3, "name_list" : [ "liu" ] } { "_id" : 1, "name_list" : [ "yang" ] } { "_id" : 2, "name_list" : [ "wang", "wang", "wang" ] } { "_id" : "6", "name_list" : [ "孙权" ] } { "_id" : "5", "name_list" : [ "孙权" ] } { "_id" : "4", "name_list" : [ "孙权" ] } { "_id" : "3", "name_list" : [ "孙权" ] } { "_id" : "2", "name_list" : [ "周瑜" ] } { "_id" : null, "name_list" : [ "liu2" ] } { "_id" : "1", "name_list" : [ "孙策" ] }
管道命令之$match:
$match用于进行数据的过滤,是能够在聚合操作中使用的命令,和find的区别是$match操作可以把结果交给下一个管道处理,而find不行。
示例:先找到age=21的数据,然后对这些数据分组
db.nor_col.aggregate({$match:{age:21}},{$group:{_id:"$num",name:{$push:"$name"}}}) 结果: { "_id" : 3, "name" : [ "liu" ] } { "_id" : 1, "name" : [ "yang" ] } { "_id" : 2, "name" : [ "wang", "wang", "wang" ] } { "_id" : "6", "name" : [ "孙权" ] } { "_id" : "5", "name" : [ "孙权" ] } { "_id" : "4", "name" : [ "孙权" ] } { "_id" : "3", "name" : [ "孙权" ] } { "_id" : "2", "name" : [ "周瑜" ] } { "_id" : null, "name" : [ "liu2" ] } { "_id" : "1", "name" : [ "孙策" ] }
管道命令之$project:
$project用于修改文档的输入输出结构,例如重命名,增加,删除字段。
示例:聚合查询之后输出name字段,不输出_id字段
db.nor_col.aggregate({$match:{age:21}},{$group:{_id:"$num",name:{$push:"$name"}}},{$project:{_id:0,name:1}}) 结果: { "name" : [ "liu" ] } { "name" : [ "yang" ] } { "name" : [ "wang", "wang", "wang" ] } { "name" : [ "孙权" ] } { "name" : [ "孙权" ] } { "name" : [ "孙权" ] } { "name" : [ "孙权" ] } { "name" : [ "周瑜" ] } { "name" : [ "liu2" ] } { "name" : [ "孙策" ] }
管道命令之$sort:
$sort用于将输入的文档排序后输出
示例: 根据num值升序排序,如果num:-1 的意思是降序排序。
db.nor_col.aggregate({$sort:{num:1}})
管道命令之$skip,$limit:
示例1:$limit的使用
db.nor_col.aggregate({$limit:1})
示例2: $skip的使用
db.nor_col.aggregate({$skip:1})
管道命令之拆分"数组" $unwind:
这个用的相对较少,可以了解为就是把["a","b","c"]这样的数组拆分出来
示例1:
db.nor_col.aggregate({$unwind:"$size"})
说明:$size是要拆解的字段
示例2:
db.nor_col.aggregate({$unwind:{path:"$size",preserveNullAndEmptyArrays:true}})
说明:preserveNullAndEmptyArrays:true表示如果有些文档没有size这个字段,那也要展示出来一个空值