聚合操作

文章目录

  • 聚合操作
  • 一、集合管道
  • 1、管道介绍
  • group中的操作表达式
  • 2、管道优化
  • 二、映射化简
  • 1、映射化简的JavaScript方法
  • 2、映射化简的特点
  • 三、单一目的聚合方法

聚合操作处理数据记录并返回计算结果。聚合操作将来自多个文档的值分组在一起,并且可以对分组的数据执行各种操作以返回单个结果。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