MongoDB 聚合框架 (1/2) - 简介

  • MongoDB 聚合框架(Aggregtaion Framework)是一个计算框架,它可以:
    • 作用在一个或几个集合上;
    • 对集合中的数据进行一系列的运算;
    • 将这些数据转化为期望的形式;
  • 从效果而言,聚合框架相当于 SQL 查询中的:
    • Group By
    • Left Outer Join
    • As等

管道(Pipeline)和步骤(Stage)

  • 整个聚合运算过程称为管道(Pipeline),它是由多个步骤(Stage)组成的,每个管道:

    • 接受一系列文档(原始数据);

    • 每个步骤对这些文档进行一系列的运算;

    • 结果文档输出给下一个步骤;

    • 原始数据 => (步骤1) => 中间结果1 => (步骤2) => 中间结果2 => ... => 最终结果。

  • 聚合运算的基本格式

pipeline = [$stage1, $stage2, ...$stageN];
db.<Collection>.aggregtae(
	pipeline,
	{options}
);
  • 聚合运算常见 步骤(Stage)

    步骤(Stage) 作用 SQL 等价运算符
    $match 过滤 WHERE
    $project 投影 AS
    $sort 排序 ORDER BY
    $group 分组 GROUP BY
    $skip / $limit 结果限制 SKIP / LIMIT
    $lookup 左外连接
    (对多表的数据关联把数据合并到一张表里进行过滤选择然后做一些运算操作)
    LEFT OUTER JOIN
  • 常见步骤中的运算符

    $match $project $group
    $eq / $gt / $gte / $lt / $lte 0/1 选择排除字段 $sum/$avg
    $and / $or / $not / $in $map/$reduce/$filter $push/$addToSet
    $geoWithin / $intersect $range $first/$last/$max/$min
    ... ... $multiply/$divide/$substract/$add ... ...
    $year/$month/$dayOfMonth/$hour/$minute/$second
    ... ...
    其他不常用步骤(Stage) 作用 SQL 等价运算符
    $unwind 展开数组 N/A
    $graphLookup 图搜索 N/A
    $facet / $bucket 分面搜索 N/A
  • 聚合运算的常见使用场景

    • 聚合查询可以用于 OLAP和 OLTP。例如:

      OLAP
      (On-Line Analytical Processing,
      联机分析处理)
      OLTP
      (On-Line Transaction Processing,
      联机事务处理)
      分析一段时间内的销售总额、均值;
      计算一段时间内的净利润;
      分析购买人群的年龄分布;
      分析学生成绩分布;
      统计员工绩效;
      计算
    -- 语句对比:查询用户表中的男性,从100以后查询20个,只返回名和姓。
    -- sql
      SELECT
        first_name as `名`,
        last_name as `姓`
      FROM users
      WHERE GENDER = '男'
      SKIP 100 
      LIMIT 20
    -- mongo
      db.users.aggregate([
        {$match : {gender : "男"}},
        {$skip : 100},
        {$limit : 20},
        {$project: {
          '名' : "$first_name",
          '姓' : "$last_name"
        }}
      ]);
    
    -- 语句对比:查询用户表中的每个部门的女性的数量,且只看数量少于10的部门。
    -- sql
    	SELECT
    		department,
    		COUNT(null) AS emp_qty,
    	FROM users
    	WHERE gender = '女'
    	GROUP BY department 
    	HAVING COUNT(*) < 10;
    -- mongo
    	db.users.aggregate([
        {$match : {gender : '女'}},	-- 匹配条件
        {$group : { 								-- 分组条件
        	_id : '$department',
        	emp_qty : {$sum : 1}	-- 每次加1,在这个分组中的时候
        }},
        {$match : {emp_qty : {$lt : 10}}} -- 最后匹配数量小于10的,超过10的就不要了。
      ]);
    
    
    // Mongo特有的$bucket。
    // 例如:把全部商品按照分段,显示每个价格区间的商品数量:[0,10)  [10,20)   [20,30)  [30,40) [40,+∞)
    db.products.aggregate([{
    	$bucket : {
    		groupBy : "$price",
    		boundaries : [0, 10, 20, 30, 40],
    		default : "Other", -- 这一行是用于最后一个价格区间
    		output : {"count" : {$sum:1}}
    	}
    }]);
    
    // Mongo特有的$facet[ˈfæsɪt],把多个$bucket操作组合起来。
    // 例如:上面的价格分段加上时间分段
    db.products.aggregate([{
      $facet : {
        price : {
          $bucket : {/*...*/}
        },
        year : { // [1890, 1901)  [1901, 1920)  未知年份
          $bucket : {
            groupBy : "$year",
    				boundaries : [1890, 1901, 1920],
    				default : "Other",
    				output : {"count" : {$sum:1}}
          }
        }
      }
    }]);
    
    

posted on 2021-03-26 15:57  Sweet小马  阅读(151)  评论(0编辑  收藏  举报

导航