开发者学堂课程【MongoDB 快速入门:MongoDB 聚合框架】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/49/detail/1001
MongoDB 聚合框架
主要内容
一、MongoDB 聚合框架的基本概念
二、基本使用
三、进阶使用
四、视图
一、MongoDB 聚合框架的基本概念
1、什么是 MongoDB 聚合框架
这节课进行 MongoDB 聚合框架的学习,首先看一下聚合框架的基本概念。聚合框架是用于在一个或几个集合上进行的一系列运算从而得到期望结果的数据集的运算框架。从效果上而言,MongoDB 聚合框架类似于 SQL 查询语言中的 GROUP BY、LEFT OUTER JOIN 即左外连接还有 AS,但 MongoDB 的聚合功能不止如此。
2、管道(Pipeline)和步骤(Stage)
MongoDB 聚合框架里面有两个很重要的概念,管道和步骤也就是对应的 Pipeline 和Stage。Pipeline 管道,管道是对数据进行处理的一个过程,它非常类似于 linux 里面的管道操作符。步骤 Stage,Stage 是指管道操作中的每一个阶段,每一个操作的步骤,在每一个步骤通常会接受一系列的原始数据,然后在这些原始数据上进行加工处理,最后生成下一步骤所需的文档。当然如果这一步骤是最终的步骤就直接返回给应用程序
3、聚合框架/管道/步骤
接下俩学习聚合框架管道和步骤的示意,比如有一个原始的数据集里面有很多的数据,中间有对应的中间结果1和2是每一个阶段执行的结果,最后进行处理作为最终的结果集返回给应用程序。这样每次的处理过程就是对应的处理步骤 stage,stage 按照顺序一步步地合起来就是整个聚合框架的管道,整个处理的方式和流程就是整个mongoDB 的聚合框架。从原始的数据集经过各个步骤的处理最终得到一个最终结果集的运算过程就是 mongoDB 的聚合框架。
二、基本使用
1、使用形式
接下来学习聚合框架的基本使用,在 mongDB 聚合框架里面最重要的参数就是pipeline,pipeline 是一个数组的形式,在数组里面每一个元素对应一个步骤 stage,将整个 pipeline 传给数据库执行就会按照 stage 一步步的去执行。最后将结果返回给客户端。
2、常用步骤(stage)运算符
接下来学习常用的 stage,比如常用的有$match 进行过滤,类似于 SQL 里面的WHERE。以及$project会进行投影,投影类似于 SQL 里面的 AS,$sort帮助进行排序,类似于ORDER BY,$group来进行分组类似于 SQL 里的 GROUP BY,还有$skip/$limit帮助进行翻页和一些查询的限制,还有类似于SQL里面左外连接的$lookup。在每一个步骤中还包含很多的子运算符,比如在$match经常用$eq表示某一个条件相等,还有$gt大于$gte大于等于等等,以及$and/$or/$not等逻辑运算符,还有表示地理位置的$geoWithin/$intersec,这些表示地理位置的运算符。在$project这个步骤,可能需要用到$map/$reduce对数组的每一个元素进行处理,还有进行加紧乘除的$multiply/$divide/$substract/$add等,还有进行日期运算的$year/$month等等子的运算符。在$group里面经常进行一些聚合操作,比如里面经常会用到的子运算符会有$sum来进行汇总,$avg表示求平均值,$push/$addToSet对数组进行操作。
此外还有一些其他的步骤运算符也是非常常用的,比如 $unwind 可以帮助展开数组,假设在数组中有三个元素$unwind 之后就会展开为三个文档,$graphLookup 可以帮助进行图搜索,以及$ facet/$bucket 可以帮助进行分面搜索。
3、为什么只有左外连接
mongoDB 里面连接 JOIN 操作只有左外连接,有以下几个原因,第一个是JOIN的操作是违反mongoDB 设计的初衷,因为JOIN操作经常要对两个表的数据进行连接操作,这些数据在物理存储的时候通常不是在在相连的区域中,读取的效率比较低。此外考虑到mongoDB是一个分布式的环境,比如可以想象JOIN操作的左右两边如果都是分片的表,当进行JOIN操作时,左边有一条数据可能在分片1上要连接的数据可能在分片2上,下一条数据可能是另外一种情况,这种情况下数据库很难保证操作的性能,基于这些原因mongoDB只提供左外连接并且要求from表也就是右边的表不能是分片表,左边的表主表可以是分片表。
4、SQL 等价运算
在 SQL 里面可能会经常使用类似于左边 SELECT 的查询语句,FIRST_NAME AS名、LAST_NAME AS姓、FROM Users 从用户、WHERE GENDER男以及SKIP 100条LIMIT 20条。对应的在mongoDB里面会使用聚合框架,第一个是{$match:{gender:‘男’}},{$skip:100}即可以跳过前100条数据,{$limit:20}只取20条数据,使用{$project}把{first_name,last_name}分别变为名和姓。
在SQL里还经常使用group by类似于左边的运算符,对应的在mongoDB里面使用聚合运算aggregation,第一阶段可以使用{$match:{gender:‘女’}},第二个可以使用{$group},{$group}里面有两个参数第一个是_id,_id假设以DEPARTMENT部门为条件进行分组,对每一条数据计算统计求和值用$sum,计算的结果放在emy_qty里面,最后可以用$match去过滤找到部门里面员工人数小于10的。
三、进阶使用
1、$unwind 操作符
接下来学习聚合框架的进阶使用,首先看$unwind操作符,比如有一条示例数据{name: ‘张三’,score:[{subject:‘语文’,score:84},{subject:‘数学’,score:90},{subject:‘外语’,score:69}]即name=张三,张三的成绩放在score数组里面分别对应的有三个元素第一个是语文成绩,第二个是数学成绩,第三个是外语成绩,如果只使用$unwind操作符就会把数据这一文档展开为三个文档{name:‘张三’,score:{subject:‘语文’,score:84}} ,{name:‘张三’,score:{subject:‘数学’,score:90}} ,{name:‘张三’,score:{subject:‘英语’,score:69}} ,分别为语文数学和外语的成绩。进一步的在$unwind下面加一个$sort的操作符,按照姓名name进行排序,在name相同的情况下按照score进行降序,这时可以看到返回的第一条结果是张三并且是科目当中最高的{name:‘张三’,score:{subject:‘数学’,score:90}}就是数学,数学的得分在三科目中最高,所以数学的成绩排在最前面。
2、分面搜索
另外常用的有分面搜索,分面搜索比如在逛一些论坛或者是博客网站的时候可以看到帖子或文章会按照不同的地区,按照不同的内容板块,或者按照不同的类别不同的标签来进行统计。比如按照板块对应的mongoDB里认为是一个桶bucket。
举例假如有很多的商品,希望按照商品的价格进行分类统计,想按照价格在[0,10),在[10,20),[20,30),[30,40)以及[40’),希望统计每一个区间里面商品的个数,对应的可以使用aggregation,$bucket这样的阶段操作符,$bucket 里面主要有以下几个参数第一个 groupBy 即要进行分组基于什么字段,使用$price 基于价格字段进行分组,第二个重要的参数是boundaries也就是在进行分组的时候,每个分割的区间是哪几个点,这里有[0,10,20,30,40]这几个分区的点。其他的放在 default,它的值是 other,如果是在区间之外的就放在 other 里面,针对每一个分组的操作要执行$sum 求和的操作,返回的结果放在 coun t里面,有时还不只是想对价格进行分类的统计,还想对年份进行分类的统计,这时看到的是期望的结果,希望把商品按照不同的价格区间进行分组,同时还希望商品按照年份来分组,这时在 mongoDB 里面仍可以通过一个查询操作进行统计,比如可以使用$facet, 在$facet 里面可以按照price价格,价格里面也是一个$bucket 桶的操作,此外除了 price,还按照年份 year 进行另外一个$bucket的运算。如果有其他统计的需要,可以加在后面,这样通过一个$facet 的操作就可以把商品按照不同的分类维度进行分类统计。
3、图搜索
此外还可以使用$graphLookup 操作符进行图搜索,比如经常在社交媒体里面要找到某个人,有很多好友在这些好友里面过滤出来有哪些特定兴趣的,比如喜欢游泳喜欢音乐的好友,将这些好友找出来可以使用$graphLookup 操作符进行查询,注意的是from 表不支持分片表。
四、视图
1、视图的概念
接下来进行视图的学习,先看一下视图的概念,在 MongoDB 里面的视图类似于 SQL中的视图,是基于一个或多个已经存在的集合创建,可以预定义聚合查询。
2、视图的作用
可以进行数据的抽象以及数据的保护,比如对于敏感的数据把敏感的字段放到视图之外,这样查询的结果就不会包含视图之外的字段,另外视图是只读的,结合上mongoDB里面基于角色的授权,也可以按角色控制数据的访问,这样就可以保护敏感的数据,让没有获得授权的人通过访问视图不能访问敏感的信息。
3、创建视图
创建视图的命令对应的是 creatView,里面主要的参数有视图的名称以及对应的聚合表达式,比如$project 将_id 字符段排除掉,将 first_name、last_name、gender、email、phone 字符段保留下来,其他的字段都不显示在视图里面。
4、删除视图
删除一个视图和删除一个集合是类似的,用 db.contact_info.drop 就可以删除视图,contact 是视图的内容。本节课到此结束,如有问题可在群里提问。