MongoDB入门实战教程(6)
本系列教程目录:
通过前面几篇的学习,作为后端开发的我们基本可以应付70%的开发场景。接下来,我们就来看点进阶一点的东西,首先是聚合查询。
1 聚合框架简介
前面的学习我们都是针对单个Collection操作的,虽然在MongoDB中针对Collection的设计就已经是无模式的,因此我们大部分场景都是针对单个Collection进行操作。
但是,我们在实际应用场景中还是会遇到想要SQL查询中的 GROUP BY、LEFT OUTER JOIN、AS等操作。
好在,MongoDB提供了一套聚合框架(Aggregation Framework),它可以帮助我们在一个或多个Collection上,对Collection中的数据进行一系列的计算,并将这些数据转化为期望的格式。
整个聚合计算的过程也被称之为管道(Pipeline),由多个步骤(Stage)组成,这一点和Jenkins Pipeline比较类似。其中,每个管道需要:
(1)接受一系列Document(原始数据)
(2)每个步骤对这些Document进行一系列的运算
(3)结果Document输出给下一个步骤
整个管道的过程如下图所示:

聚合计算的基本格式如下所示:
pipeline = [$stage1, $stage2, ...$stageN]; db.<CollectionName>.aggregate(
pipeline,
{ options }
);
2 聚合操作实例
示例数据数据库
这里我们使用《MongoDB入门实战教程(3)》中使用Mongo Tools进行恢复的Mock数据库中的orders集合来进行应用。
在orders集合中,约有100000条记录。

每个order文档的数据模型如下所示:


练习1:目前为止的订单总销量
假设我们需要针对orders集合进行一个操作,计算到目前为止的所有订单的总销售额:
db.orders.aggregate([
{ $group:
{
_id: null,
total: { $sum: "$total" }
}
}
]);
这里我们使用到了一个常见的步骤(Stage):$group,它和SQL中的GROUP BY等价,用于对数据进行分组。这里我们仅仅是做一个求和,不需要对谁进行分组。
然后,我们还用到了一个分组步骤中常用的运算符:$sum,它和SQL中的SUM等价,用于对指定列的数据进行求和。这里我们需要对total字段进行一个求和。
下图是查询结果:

练习2:某个日期区间的订单金额汇总
假设我们需要查询在2019年第一季度已完成订单的订单总金额和订单总数。
说明:第一季度为1月1日~3月31日,订单状态为completed。
db.orders.aggregate([
// 步骤1:匹配条件
{ $match: { status: "completed", orderDate: {
$gte: ISODate("2019-01-01"),
$lt: ISODate("2019-04-01") } } },
// 步骤二:聚合订单总金额、总运费、总数量
{ $group: {
_id: null,
total: { $sum: "$total" },
shippingFee: { $sum: "$shippingFee" },
count: { $sum: 1 } } },
{ $project: {
// 计算总金额
grandTotal: { $add: ["$total", "$shippingFee"] },
count: 1,
_id: 0 } }
])
可以看到,这是一个较为复杂的查询,我们可以将其分为三步:
第一步,使用$match进行匹配,这一点是做的SQL中的WHERE操作。
第二步,使用$group进行分组,目的是为了使用SUM运算符求和。
第三步,使用$project进行投影,目的是选择需要的或排除不需要的字段显示。
下图是查询结果:

3 MQL vs SQL
分页查询对比
在SQL中常使用SKIP 和 LIMIT 进行分页查询,在MQL中也有等价操作:
-- SQL
SELECT
FIRST_NAME AS `名`,
LAST_NAME AS `姓`
FROM Users
WHERE GENDER = '男'
SKIP 100
LIMIT 20
-- MQL
db.users.aggregate([
{$match: {gender: "男"}},
{$skip: 100},
{$limit: 20},
{$project: {
'名': '$first_name',
'姓': '$last_name'
}}
]);
分组查询对比
在SQL中常使用GROUP BY + HAVING 的分组高级查询,在MQL中也有等价操作:
-- SQL
SELECT DEPARTMENT,
COUNT(NULL) AS EMP_QTY
FROM Users
WHERE GENDER = '女'
GROUP BY DEPARTMENT HAVING
COUNT(*) < 10
-- MQL
db.users.aggregate([
{$match: {gender: '女'}},
{$group: {
_id: '$DEPARTMENT’,
emp_qty: {$sum: 1}
}},
{$match: {emp_qty: {$lt: 10}}}
]);
unwind
在MQL中有一个特有的步骤 unwind,它可以实现将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
> db.students.findOne()
{
name:'张三',
score:[
{subject:'语文',score:84},
{subject:'数学',score:90},
{subject:'外语',score:69}
]
} > db.students.aggregate([{$unwind: '$score'}])
{name: '张三', score: {subject: '语文', score: 84}}
{name: '张三', score: {subject: '数学', score: 90}}
{name: '张三', score: {subject: '外语', score: 69}}
4 总结
本文简单介绍了MongoDB的Aggregation Framework 以及 如何使用聚合框架进行聚合查询。
下一篇,我们会学习MongoDB的模式设计中的一些设计模式。
参考资料
Microsoft Doc,使用ASP.NET Core和MongoDB创建WebAPI
唐建法,《MongoDB高手课》(极客时间)
郭远威,《MongoDB实战指南》(图书)

△推荐订阅学习

MongoDB入门实战教程(6)的更多相关文章
- Kafka入门实战教程(7):Kafka Streams
1 关于流处理 流处理平台(Streaming Systems)是处理无限数据集(Unbounded Dataset)的数据处理引擎,而流处理是与批处理(Batch Processing)相对应的.所 ...
- ZooKeeper入门实战教程(一)-介绍与核心概念
1.ZooKeeper介绍与核心概念1.1 简介ZooKeeper最为主要的使用场景,是作为分布式系统的分布式协同服务.在学习zookeeper之前,先要对分布式系统的概念有所了解,否则你将完全不知道 ...
- Node+Express+MongoDB+Socket.io搭建实时聊天应用实战教程(一)--MongoDB入门
前言 本文并不是网上流传的多少天学会MongoDB那种全面的教程,而意在总结这几天使用MongoDB的心得,给出一个完整的Node+Express+MongoDB+Socket.io搭建实时聊天应用实 ...
- Node+Express+MongoDB + Socket.io搭建实时聊天应用实战教程(二)--node解析与环境搭建
前言 本来开始写博客的时候只是想写一下关于MongoDB的使用总结的,后来觉得还不如干脆写一个node项目实战教程实战.写教程一方面在自己写的过程中需要考虑更多的东西,另一方面希望能对node入门者有 ...
- MongoDB入门必读(概念与实战并重)
MongoDB入门必读(概念与实战并重) 一.概述 MongoDB是一个基于分布式文件存储的数据库开源项目.由C++语言编写.旨在为WEB应用提供可护展的高性能数据存储解决方案. MongoDB是一个 ...
- mybatis实战教程(mybatis in action),mybatis入门到精通
转自:http://www.yihaomen.com/article/java/302.htm (读者注:其实这个应该叫做很基础的入门一下下,如果你看过hibernate了那这个就非常的简单) (再加 ...
- mybatis实战教程(mybatis in action),mybatis入门到精通(转)
转自:http://www.yihaomen.com/article/java/302.htm (读者注:其实这个应该叫做很基础的入门一下下,如果你看过Hibernate了那这个就非常的简单) (再加 ...
- mongodb入门教程二
title: mongodb入门教程二 date: 2016-04-07 10:33:02 tags: --- 上一篇文章说了mongodb最基本的东西,这边博文就在深入一点,说一下mongo的一些高 ...
- mongodb入门教程
title: mongodb入门教程 date: 2016-04-06 14:47:18 tags: --- 为什么要认识呢,因为这玩意就一傻逼 借用一下百科的介绍 MongoDB 是一个介于关系数据 ...
- MongoDb 入门教程
MongoDb 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的. 它是可扩展的高性能数据存储解决方案,经常被用于非关系型数据的存储,能存储海量的数据. 常 ...
随机推荐
- 史上最全EffectiveJava总结(二)
方法 49.检查参数的有效性 每次编写方法或构造函数时,都应该考虑参数存在哪些限制,并在文档中记录下来,然后在方法的开头显式地检查. 如果没有在方法开头就验证参数,可能会违反故障原子性.因为方法可能会 ...
- 【SpringMVC】处理 JSON:使用 HttpMessageConverter
处理 JSON:使用 HttpMessageConverter 处理 JSON 加入 jar 包: 编写目标方法,使其返回 JSON 对应的对象或集合 在方法上添加 @ResponseBody 注解 ...
- AspNetCore Json序列化设置
AspNetCore 中的Json序列化处理已经默认使用Newtonsoft.Json库了... 比如像MVC中: public I 不过使用过程中会发现一些问题,其实这算默认设置吧: Json序列化 ...
- SLAM导航全栈书的正确打开姿势
SLAM导航全栈书的正确打开姿势 随着人工智能.机器人.无人驾驶等技术的蓬勃发展,作为底层技术基石的SLAM也逐渐被大家所熟知.人工智能技术如果仅仅停留在虚拟的网络和数据之中的话,那么它挖掘并利用知识 ...
- H5 电商新势力崛起:ZKmall模板商城 H5 版本的高性能开发秘籍
H5电商新势力的崛起中,ZKmall模板商城H5版本以其高性能和灵活性脱颖而出.以下是ZKmall模板商城H5版本的高性能开发秘籍,结合技术选型.架构优化与核心实践,为全场景电商应用提供高效解决方案: ...
- TortoiseGit安装(Windows10环境)
1.前往官网下载 https://tortoisegit.org/download/ 根据自己系统位数进行选择 2.双击运行 3.默认即可,第一个是基于PuTTY的SSH客户端,与Windows兼容更 ...
- Electron35-DeepSeek桌面端AI系统|vue3.5+electron+arco客户端ai模板
2025跨平台ai实战electron35+vite6+arco仿DeepSeek/豆包ai流式打字聊天助手. electron-deepseek-chat:实战ai大模型对话,基于vue3.5+el ...
- git 更新和强制更新失败
Your local changes to the following files would be overwritten by mergeerror: Your local changes to ...
- 贪心算法——Demo1
题干: 假设你是一位很棒的家长,想要给你的孩子们一些小饼干.但是,每个孩子最多只能给一块饼干. 对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸:并且每块饼干 j,都有 ...
- 通过Linux包管理器提升权限
免责声明:本文所涉及的技术仅供学习和参考,严禁使用本文内容从事违法行为和未授权行为,如因个人原因造成不良后果,均由使用者本人负责,作者及本博客不承担任何责任. 前言 在Linux系统中,apt和yum ...