一、基本概念
(一)什么是聚合框架
聚合框架(Aggregation Framework)是用于在一个或几个集合上进行的一系列运 算从而得到期望的数据集的运算框架。
从效果而言,聚合框架相当于 SQL 查询中的:
- GROUP BY
- LEFT OUTER JOIN
- AS
- …
- 但聚合框架的作用不限于此
(二)管道(Pipeline)和步骤(Stage)
管道(Pipeline):
- 聚合框架对数据进行处理的过程。
- 与 Linux 管道有类似之处;
步骤(Stage):
- 步骤(Stage)是指管道中的一步操作。每个步骤:
- 接受一系列文档(原始数据);
- 在这些文档上进行一系列运算;
- 生成下一个步骤所需的文档;
聚合框架管道和步骤的示意,一个原始的数据集,有很多的数据,中间有对应的结果, 1 和 2 是每一个阶段执行的结果,最后处理作为最终的一个结果集返回给应用程序。
每一次的处理过程对应的一个处理的步骤,这些步骤按照顺序整合起来,就是聚合框架 的管道,从原始的数据集经过每一个步骤的处理,整个处理的方式和流程,就是 MongoDB 聚合框架。
二、基本使用
(一)使用形式
pipeline = [$stage1, $stage2, ...$stageN]; db.<COLLECTION>.aggregate( pipeline, { options } );
聚合框架的基本使用,在 MongoDB 聚合框架里面最重要的一个参数就是 Pipeline, Pipeline 是一个数组的形式,在数组里面每一个元素表示一个对应的步骤,然后把整个 Pipeline 传给数据库进行执行,然后就按照这些步骤进行执行,最后把结果返回给客户端。
(二)常用步骤(stage)运算符 1
常用的 Stage 有$Match,进行过滤,类似于 SQL 里面的 WHERE 子句;$Project, 进行投影,类似于 SQL 里面的 AS;$Sort,会进行排序,类似于 ORDER BY;$Group 来 进行分组,类似于 SQL 里面的 GROUP BY;$Skip 和$Limit,进行翻页和查询的限制; $LookUp,类似于 SQL 里面左外连接。
(三)子运算符
在每一个步骤里面还包含很多的子运算符,在$Match 里面经常会用到了 EQ,表示某 个条件相等,$GT 大于$GTE 大于等于等; 还有$And/$All 这些逻辑运算符,还有表示地 理位置的,例如$Geowithin/$Intersect,表示地理位置运算的运算符,$Project 阶段步 骤,可能会用到$Map,$Reduce 来对数组的每个元素进行处理。
还有进行加减乘除的,例如$Multiply、$Divide、$Subtract、$Add 等;进行日期运 算的像$Year、$Month 等子的运算符,在$Group 里面经常进行聚合操作,例如子运算 符经常会用到$Sum 来进行汇总、$Avg 求平均值、$Push、$AddToSet 来对数组进行 操作。
(四)常用步骤(stage)运算符 2
还有其他的常用步骤运算符$Unwind 可以展开数组,例如在数组中有三个元素,到了 $Unwind 后就会展开成三个文档,形成三条记录。$GraphLookUp 可以进行图搜索, $Facet 和$Bucket,进行分面搜索。
(五)为什么只有左外连接?
MongoDB里面连接Join操作只有左外连接,因为Join这种操作上是违反MongoDB 设计的初衷的,这样操作经常要对两个表的不同数据进行连接操作,这些数据在物理存储的 时候,通常不是在相邻的区域里面,读取的效率比较低。
此外 MongoDB 是一个分布式的环境,校验操作的左右两边如果都是一个分片的表, 当进行 Join 操作的时候,左边有一个又有一条数据,它可能在分片一上要连接的一个数据 可能在分片二上,下一条数据可能又是另外一种情况,这种情况下数据库很难保证整个操作 的性能。
基于这些原因,MongoDB 只提供左外连接,并且要求 From 表不能是分片表,左边 的表主表可以是分片表,在 SQL 里面会使用类似于左边这样的一个查询语句。
(六)SQL 等价运算
在 SQL 里面还会使用 Group BY 类似于左边这样的一个运算符,对应的在 MongoDB 里面是使用聚合运算 Aggregate。
三、进阶使用
(一)$unwind
$Unwind 的操作符,这里有示例一条数据,Name 等于张三,张三的成绩放在 Score 这个数组里面,分别对应有三个元素,第一个是语文成绩,第二个是数学成绩,第 三个是外语成绩。
如果只使用$Unwind 的操作符,就会把这一个数据一条文档展开成三个文档,分别是 语文、数学和外语的成绩,进一步在$Unwind 的下面加一个$Sort 的操作符,按照姓名 Name 进行排序,在 Name 相同的情况下,按照 Score 进行降序。可以看到返回的第一 条结果就是张三并且是他科目当中成绩最高的,数学的得分在三科目当中最高,所以数学的 成绩会排在最前面。
(二)分面搜索
还有常用的像分面搜索,例如逛一些论坛,或者是博客网站的时候,经常会看到帖子或 者是文章,会按照不同的地区,不同的内容板块,不同的类别,不同的标签来进行统计。
每一个内容板块对应到 MongoDB 里,可以把它认为一个是 Bucket。
例一:
有很多的商品,我们希望按照商品的价格来进行分类统计,想按照价格在0~10之间,10~20之间,还有20~30,30~40以及大于40的,希望能够统计每一个区间里面商品的个数,对应可以用aggregation,然后使用$bucket这样的阶段操作符。
$Bucket 主要有这几个参数,第一个是 GroupBy,也就是要进行分组,使用$Price, 基于价格字段进行分组。
第二个参数是 Boundaries,在进行分组的时候,每个分割的区间有 00:00、2:00、3: 00、4:00 这几个分区的点,其他的放在 Default,它的值是 Other.
针对每一个分组的操作,要执行$Sum,求和的操作,返回的结果放在 Count 里面。
例二:
商品按照不同的价格区间来进行分组的同时还希望商品按照年份来进行分组。商品按照不同的价格区间来进行分组的同时还希望商品按照年份来进行分组。
在 MongoDB 里面,可以通过$Facet 查询操作来完成这样的统计,可先按照 Price 也就是价格进行一个$Bucket 的操作,此外除了 Price 之外,还按照年份进行另外一个的运 算。如果有其他的一个统计的需要,可以继续加在后面,通过一个$Facet 的操作,就可以 把商品按照不同的维度进行分类统计。
(三)图搜素
可以使用$GraphLookUp 操作符来进行图搜索。
四、视图
(一)视图的概念:
- 基于一个或多个其他集合创建
- 预定义聚合查询
- 类似于 SQL 中的视图
作用:
- 数据抽象 保护敏感数据的一种方法
- 将敏感数据投影到视图之外
- 只读
- 结合基于角色的授权,可按角色访问信息
(二)创建视图
对于敏感数据,把数据的敏感字段放到视图之外,查询的结果里面就不会包含视图之外 的字段,视图还是只读的。结合上 MongoDB 里基于角色的权限授权,可以按角色去控制 数据的访问,保护这些敏感的数据,让没有获得授权的人通过访问视图不能够访问到敏感的 信息。
创建视图的命令对应的是 CreateView,其中包含的参数视图的名称和对应的聚合表 达式,这里使用的是$Project,排除_ID,保留 First_Name、Last_Name、Gender、 Email、Phone。
(三)删除
删除视图的话和删除一个集合是类似的,我们用“DB.+视图的名称+.Dorp()”就可以 删除视图。
快速掌握MongoDB核心技术目录
电子书下载:《玩转MongoDB从入门到实战》 | https://developer.aliyun.com/article/780915 |
走进 MongoDB | https://developer.aliyun.com/article/781079 |
MongoDB聚合框架 | https://developer.aliyun.com/article/781095 |
复制集使用及原理介绍 | https://developer.aliyun.com/article/781137 |
分片集群使用及原理介绍 | https://developer.aliyun.com/article/781104 |
ChangeStreams 使用及原理 | https://developer.aliyun.com/article/781107 |
事务功能使用及原理介绍 | https://developer.aliyun.com/article/781111 |
MongoDB最佳实践一 | https://developer.aliyun.com/article/781139 |
MongoDB最佳实践二 | https://developer.aliyun.com/article/781141 |