聚合操作
聚合操作处理数据记录并返回计算结果。聚合操作将来自多个文档的值分组在一起,并且可以对分组的数据执行各种操作以返回单个结果。MongoDB提供了三种执行聚合的方法:聚合管道,map-reduce函数和单一目的聚合方法。
一、集合管道
1、管道介绍
聚合管道是一个基于数据处理管道概念建模的数据聚合框架。文档进入多阶段管道,一个管道处理完毕后交给下一个管道,该管道将文档转换为汇总结果。
语法:db.collection_name.aggregate([{管道1},{管道2},{管道3},…])
常用的管道操作 | |
---|---|
$project | 修改输入文档的结构。可以用来重命名、增加或修改域,也可以用于创建计算结果以及嵌套文档。 |
$match | 用于过滤数据,只输出符合条件的文档。使用MongoDB的标准查询操作。 |
$limit | 用来限制MongoDB聚合管道返回的文档数 |
$skip | 在聚合管道中跳过指定数量的文档,并返回余下的文档 |
$group | 将集合中的文档分组,可用于统计结果 |
$sort | 将输入文档排序后输出。 |
group中的操作表达式
表达式 | 描述 |
---|---|
$sum | 计算总和 |
$avg | 计算平均值 |
$min | 获取集合中所有文档对应值的最小值 |
$max | 获取集合中所有文档对应值得最大值 |
$first | 根据资源文档的排序获取第一个文档数据 |
$last | 根据资源文档的排序获取最后一个文档数据 |
练习:
1.查询每个年龄段的人员数量:
db.school.aggregate([{$group:{_id:"$age",total:{$sum:1}}}])
2.查询总共有多少人
db.school.aggregate([{$group:{_id:null,total:{$sum:1}}}])
2、管道优化
-
$sort
+$match
顺序优化如果管道中,sort后面跟着match,可以先使用match进行筛选,这样会减少之后排序的对象。
-
$skip
+$match
顺序优化如果你的管道中,skip后面跟着limit,优化器会把limit移到skip前面,这个时候limit的会值加上skip的个数。
-
$redact
+$match
顺序优化 -
$ project
+$ skip
或$ limit
序列优化 -
$ sort
+$ limit
合并 -
$ limit
+$ limit
合并 -
$ skip
+$ skip
合并 -
$ match
+$ match
合并 -
$ lookup
+$ unwind
合并 -
$ sort
+$ skip
+$ limit
顺序 -
$ limit
+$ skip
+$ limit
+$ skip
顺序
二、映射化简
1、映射化简的JavaScript方法
在MongoDB中,map-reduce操作使用自定义javaScript函数将值映射或关联到键。如果一个键具有映射到它的多个值,则该操作会将键的值减少到单个对象。
例如,当处理一个文档的时候,映射函数可以映射多个键值对或者一个也不映射。映射化简还可以在结束的时候使用JavaScript对聚合结果做最后的修改,例如附加的计算。
2、映射化简的特点
在MongoDB中,map-reduce操作可以将结果写入集合或内联返回结果。如果将map-reduce输出写入集合,则可以在同一输入集合上执行随后的map-reduce操作,这些操作将替换结果,合并结果或归约结果与先前结果合并。
如果选择映射化简操作的即时返回结果,这些文档一定要在BSON文档大小
限制以内,当前这个限制是16MB。
MongoDB支持对分片集合进行 map-reduce操作。Map-reduce操作还可以将结果输出到分片集合。
三、单一目的聚合方法
MongoDB还提供db.collection.count()
和 db.collection.distinct()
。
所有这些操作都汇总了单个集合中的文档。尽管这些操作提供了对常见聚合过程的简单访问,但是它们缺乏聚合管道和映射减少的灵活性和功能。
> db.goods.find()
{ "_id" : 1, "type" : 1 }
{ "_id" : 2, "type" : 2 }
{ "_id" : 3, "type" : 3 }
{ "_id" : 4, "type" : 2 }
{ "_id" : 5, "type" : 2 }
{ "_id" : 6, "type" : 3 }
> db.goods.distinct("type")
[ 1, 2, 3 ]
> db.goods.count()
6