本系列教程目录:

MongoDB入门实战教程(1)

MongoDB入门实战教程(2)

MongoDB入门实战教程(3)

MongoDB入门实战教程(4)

MongoDB入门实战教程(5)

通过前面几篇的学习,作为后端开发的我们基本可以应付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实战指南》(图书)

△推荐订阅学习

作者:周旭龙

出处:https://edisonchou.cnblogs.com

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

MongoDB入门实战教程(6)的更多相关文章

  1. Kafka入门实战教程(7):Kafka Streams

    1 关于流处理 流处理平台(Streaming Systems)是处理无限数据集(Unbounded Dataset)的数据处理引擎,而流处理是与批处理(Batch Processing)相对应的.所 ...

  2. ZooKeeper入门实战教程(一)-介绍与核心概念

    1.ZooKeeper介绍与核心概念1.1 简介ZooKeeper最为主要的使用场景,是作为分布式系统的分布式协同服务.在学习zookeeper之前,先要对分布式系统的概念有所了解,否则你将完全不知道 ...

  3. Node+Express+MongoDB+Socket.io搭建实时聊天应用实战教程(一)--MongoDB入门

    前言 本文并不是网上流传的多少天学会MongoDB那种全面的教程,而意在总结这几天使用MongoDB的心得,给出一个完整的Node+Express+MongoDB+Socket.io搭建实时聊天应用实 ...

  4. Node+Express+MongoDB + Socket.io搭建实时聊天应用实战教程(二)--node解析与环境搭建

    前言 本来开始写博客的时候只是想写一下关于MongoDB的使用总结的,后来觉得还不如干脆写一个node项目实战教程实战.写教程一方面在自己写的过程中需要考虑更多的东西,另一方面希望能对node入门者有 ...

  5. MongoDB入门必读(概念与实战并重)

    MongoDB入门必读(概念与实战并重) 一.概述 MongoDB是一个基于分布式文件存储的数据库开源项目.由C++语言编写.旨在为WEB应用提供可护展的高性能数据存储解决方案. MongoDB是一个 ...

  6. mybatis实战教程(mybatis in action),mybatis入门到精通

    转自:http://www.yihaomen.com/article/java/302.htm (读者注:其实这个应该叫做很基础的入门一下下,如果你看过hibernate了那这个就非常的简单) (再加 ...

  7. mybatis实战教程(mybatis in action),mybatis入门到精通(转)

    转自:http://www.yihaomen.com/article/java/302.htm (读者注:其实这个应该叫做很基础的入门一下下,如果你看过Hibernate了那这个就非常的简单) (再加 ...

  8. mongodb入门教程二

    title: mongodb入门教程二 date: 2016-04-07 10:33:02 tags: --- 上一篇文章说了mongodb最基本的东西,这边博文就在深入一点,说一下mongo的一些高 ...

  9. mongodb入门教程

    title: mongodb入门教程 date: 2016-04-06 14:47:18 tags: --- 为什么要认识呢,因为这玩意就一傻逼 借用一下百科的介绍 MongoDB 是一个介于关系数据 ...

  10. MongoDb 入门教程

    MongoDb 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的. 它是可扩展的高性能数据存储解决方案,经常被用于非关系型数据的存储,能存储海量的数据. 常 ...

随机推荐

  1. 【Python】导出docx格式Word文档中的文本、图片和附件等

    [Python]导出docx格式Word文档中的文本.图片和附件等 零.需求 为批量批改学生在机房提交的实验报告,我需要对所有的实验文档内容进行处理.需要批量提取Word文档中的图片和附件以便进一步检 ...

  2. .NET 原生驾驭 AI 新基建实战系列(二):Semantic Kernel 整合对向量数据库的统一支持

    1. 引言 在人工智能(AI)应用开发迅猛发展的今天,向量数据库作为存储和检索高维数据的重要工具,已经成为许多场景(如自然语言处理.推荐系统和语义搜索)的核心组件. 对于.NET生态系统的开发者而言, ...

  3. spring的控制反转(IoC)

    ioc的作用: 削减计算机程序的耦合(解除我们代码中的依赖关系 解耦的思路: 第一步:使用反射来创建对象,而避免使用new关键字. 第二步:通过读取配置文件来获取要创建的对象全限定类名

  4. cglib 代理类 自己equals自己 返回false

    简单的cglib代理示例 普通的 Java 类 package cglib; public class UserService { public void saveUser(String userna ...

  5. 关于symfony报错: Oops An Error Occurred ,The server returned a “500 Internal Server Error“

    symfony3.4 开发环境正常,生产环境访问任何路由都报错: Oops! An Error Occurred The server returned a "500 Internal Se ...

  6. excel使用VBA连接access

    需要的引用: 下面的代码涉及excel对access数据库的增删改查,可以按照需要查找使用 1 '远程链接模块 2 Option Explicit 3 Dim con As New ADODB.Con ...

  7. Ubuntu堡垒机搭建与设备管理指南

    以下是基于Ubuntu系统搭建堡垒机并集成设备管理的详细步骤和注意事项: 一.堡垒机搭建步骤 系统准备 sudo apt update && sudo apt upgrade -y s ...

  8. 一款Windows平台上的开源Ark工具——OpenArk

    简介 OpenArk是一款Windows平台上的开源Ark工具. Ark是Anti-Rootkit(对抗恶意程序)的简写, OpenArk目标成为逆向工程师.编程人员的工具,同时也能为那些希望清理恶意 ...

  9. heapdump敏感信息提取工具-heapdump_tool(二),附下载链接。

    ​ heapdump敏感信息查询工具,例如查找 spring heapdump中的密码明文,AK,SK等 下载链接: heapdump_tool下载链接:heapdump_tool下载 声明: 此工具 ...

  10. IO流-转换流、序列化流--java进阶day14

    1.转换流 转换流本质还是字符流的子类 转换流的作用 1.可以按照指定的编码进行读写操作 我们使用的IO流,默认格式都是UTF-8,如果一个文件是GBK格式,在读写的时候就会乱码,此时就可以使用转换流 ...