MongoDB高手课_MongoDB_NoSQL-极客时间极客时间推出的MongoDB高手课是帮助互联网从业者学习MongoDB、NoSQL的在线课程,极客时间是面向IT领域的知识服务产品,致力于帮助用户轻松学习,高效学习。https://time.geekbang.org/course/intro/253

一. MongoDB聚合框架

MongoDB聚合框架(Aggregation Framewrok)用于对集合中的数据进行一系列的运算,并将这些数据转化为所期望的形式来展示。

1. 聚合框架的作用

聚合框架 == SQL中的 GROUP BY、LEFT OUTER JOIN、AS 等

2. 聚合运算的使用场景

  • OLTP:计算
  • OLAP:统计、分析、汇总

3. 聚合运算的过程

  • 管道(Pipeline):整个聚合运算过程
  • 步骤(Stage):管道由多个步骤组成。
  • 聚合运算过程:管道接收文档(原始数据),在每个步骤中对这些文档进行一系列的运算,并将结果文档输出给下一个步骤。

4. 聚合运算的基本格式

pipeline = [$stage1, $stage2, ... $stageN];
db.<COLLECTION>.aggregate(
    pipline,
    { options }
);

5. 常用步骤

步骤作用SQL等价运算符
$match过滤WHERE
$project投影:选择需要的或排除不需要的字段AS
$sort排序ORDER BY
$group分组GROUP BY
$skip结果限制:跳过多少条记录SKIP
$limit结果限制:只返回多少条记录LIMIT
$lookup左外连接LEFT OUTER JOIN
$unwind展开数组
$graphLookup图搜索
$bucket分面搜索:把记录进行分组
$facet分面搜索:把几个$bucket运算放在一个$facet中完成,一次性展示几种分组结果

6. 步骤中常用的运算符

步骤

$match

$project

$group

运算符

$eq/$gt/$gte/$lt/$lte
$and/$or/$not/$in
$geoWithin/$intersect

......

$map/$reduce/$filter
$range
$multiply/$divide/$substract/$add
$year/$month/$dayOfMonth/$hour/$minute/$second

......

$sum/$avg
$push/$addToSet
$first/$last/$max/$min

......

7. 代码示例

注意:字段名前带$说明是集合中已有字段,字段名前不带$说明是要新增加的字段。

# $match、$skip、$limit、$project
# 从users集合中查找所有男性,跳过100个,只查出20个,只返回'名'和'姓'
db.users.aggregate([
  { $match: { gender: '男' } },
  { $skip: 100 },
  { $limit: 20 },
  { $project: 
    {
      '名': '$first_name',
      '姓': '$last_name'
    }
  }
]);


# $group
# 从users集合中查找所有女性,按department分组并计算员工数量,只看小于10个人的department
# emp_qty: { $sum: 1 }  员工数量计算方法:每当看到一条数据,就$sum:1,所以看到多少员工文档就加了多少次,结果就是该部门的员工总量
# emp_qty: { $lt: 10 }  员工数量要小于10
db.users.aggregate([
  { $match: { 'gender' : '女' }},
  { $group: {
      _id: '$department'
      emp_qty: { $sum: 1 }    
  }},
  { $match: { emp_qty: { $lt: 10 }}}
])


# $unwind
# students集合中数据格式
#{
#  name: '张三',
#  score: [
#    { subject: '语文', score: 84 },
#    { subject: '数学', score: 90 },
#    { subject: '外语', score: 69 }
#  ]
#}
# 使用$unwind将数组score展开
db.students.aggregate([$unwind: '$score'}])
# 展开后的结果
#{ name: '张三', score: {subject: '语文', score: 84 }}
#{ name: '张三', score: {subject: '数学', score: 90 }}
#{ name: '张三', score: {subject: '外语', score: 69 }}


# $bucket
# 使用$bucket把记录进行分组
# 使用$bucket按price的区间 [0,10),[10,20),[20,30),[30,40),其他 进行分组
# output: { 'count': { $sum: 1 }} 计算每个区间中有多少条记录并返回
db.products.aggregate([{
  $bucket: {
    groupBy: '$price',
    boundaries: [0, 10, 20, 30, 40],
    default: 'Other',
    output: { 'count': { $sum: 1 }}
  }
}])


# ¥facet 一次性展示几种分组结果
db.products.aggregate([{
  $facet: {
    price: {
      $bucket: {...}
    },
    year: {
      $bucket: {...}
    }
  }
}])

二. MongoDB聚合查询实例

1. 计算所有订单的总销售额

# _id: null表示没有分组,将所有表作为一个大分组
# 指定一个新字段total,其内容是把所有记录的$total字段值加起来
db.orders.aggregate([{
    $group:{
        _id: null,
        total: { $sum: "$total"}
    }
}])
# 结果 { "_id" : null, "total" : NumberDecimal("44019609") }

2. 查询2019年1月1日-3月31日已完成的订单总金额和订单总数

# MongoDB中要使用ISODate将数据转化为合适的日期格式
db.orders.aggregate([
  // 1. 匹配条件(一般都要先做匹配)
  { $match: {
      status: "completed",
      orderDate: {
        $gte: ISODate('2019-01-01'),
        $lt: ISODate('2019-04-01')
      }
  }}, 
  // 2. 聚合订单总金额、总运费、总数量
  { $group: {
      _id: null,
      total: { $sum: "$total" },
      shippingFee: { $sum: "$shippingFee" },
      count: { $sum: 1 },
  }}, 
  // 3. 投影时增加新字段grandTotal来计算$total与$shippingFee相加的总金额
  { $project: {
      grandTotal: { $add: ["$total", "$shippingFee"] },
      count: 1,
      _id: 0
  }}
])
# 结果 { "count" : 5875, "grandTotal" : NumberDecimal("2636376.00") }

三. 使用Compass把MQL转成Node.js语句

 

 

参考文章:

《MongoDB高手课》学习记录(第五天) - SegmentFault 思否今天学习的是《09 | 实验:聚合查询》章节,主要内容是聚合部分的练习。但其实就讲了一个例子,选梳理了一下语法实现。然后演示了怎么用compass工具来可视化的生成聚合查询。https://segmentfault.com/a/1190000021378569?utm_source=sf-similar-article

MongoDB高手课学习笔记(一,再入门)_君陌先生的博客-CSDN博客_mongodb 高手课这是极客时间-MongoDB高手课的学习笔记,第一章:再入门.按照数据库排名网站db-engines.com的统计,最近几年MongoDB一直保持在前四五名,前面几位是年龄30多岁的关系型数据库(Oracle,Mysql,SQLServer,PostgreSQL).https://blog.csdn.net/weixin_42008012/article/details/108092240?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-0.pc_relevant_antiscanv2&spm=1001.2101.3001.4242.1&utm_relevant_index=3 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐