【Mongodb-04】Mongodb聚合管道操作基本功能

Mongodb系列整体栏目


内容链接地址
【一】Mongodb亿级数据性能测试和压测https://zhenghuisheng.blog.csdn.net/article/details/139505973
【二】springboot整合Mongodb(详解)https://zhenghuisheng.blog.csdn.net/article/details/139704356
【三】亿级数据从mysql迁移到mongodb辛酸历程https://zhenghuisheng.blog.csdn.net/article/details/140302930
【四】Mongodb聚合管道操作基本功能https://zhenghuisheng.blog.csdn.net/article/details/140402214

mongodb聚合操作基本功能

  • 一,mongodb聚合操作基本功能
      • 1,单一聚合
      • 2,聚合管道 + 聚合操作符
        • 2.1,Count
        • 2.2,SUM
        • 2.3,Group By
        • 2.4,分组+排序
        • 2.5,多字段分组+时间格式化
        • 2.6,Group By + Having
        • 2.7,Where
        • 2.8,子查询
        • 2.9,分页
        • 2.10,连表查询

一,mongodb聚合操作基本功能

在mysql中,允许一些匹配,分组,排序,分页,求和以及多表之间的连表操作,在mongodb中,这些操作也是可以实现的,内部就是通过聚合操作实现。在mongodb中,聚合操作主要有三大类操作,分别是: 单一作用聚合、聚合管道、MapReduce ,在mongodb5.0开始,mapReduce被废弃,因为能通过MapReduce实现的功能,都可以通过这个聚合管道实现,并且聚合管道的效率还远高于MapReduce,因此本文主要是了解单一管道和聚合管道。

在了解聚合管道之前,可以先通过官方文档的教程以及如何使用:mongodb聚合管道的使用

管道的模型如下,其设计理念就是通过流水线的模式,每一个步骤处理一个操作,,每一个步骤处理完的结果传给下一个步骤,最后将结果给返回

请添加图片描述

在官网中,给了一个 sql-聚合 的映射图标,通过sql中的语法和者术语来更加清楚的了解 聚合操作的概念和使用

请添加图片描述

1,单一聚合

假设此时有一张orders的订单集合,类似于mysql中的orders订单表,在mongodb中对这些单一聚合提供了简单访问,如以下获取文档的总个数,去重等,纯原生的方式实现数据的获取,在性能上没有聚合管道的效率高

db.orders.estimatedDocumentCount(),  
db.orders.countDocument(),
db.orders.distinct()

2,聚合管道 + 聚合操作符

在官方文档中给了很多的聚合阶段的方式,接下来主要是结合官方提供的映射图标的文档,来理解mongodb中常用的一些聚合方式。在讲解聚合管道之前,先提供一些mongodb内部的一些操作符,类似于mysql的一些聚合函数,如比较操作符,日期操作符,算术表达式操作符等等。通过管道再结合对应的操作符,来实现对文档的查询,从而使得mongodb可以和关系型数据库一样的操作流程,并通过json的数据格式,让整个查询更加的灵活

在这里插入图片描述

2.1,Count

在mysql中,计算一张表的数据有多少条,可以直接使用 count(*) 命令

select count(*) as count from orders

在mongodb中聚合管道的操作命令如下,_id为空就是表示不根据某个字段进行分组,即所有文档在同一个组里面,里面的 {$sum:1} 表示的是一个累计计数器的效果,表示查询出文档的条数,这里的每有一条文档那么这个计数器就会加1。比如查询出来是100条,那么count的值就是100,和上面mysql的as count的操作是一样的

db.orders.aggregate([{$group:{_id:null,count:{$sum:1}}}
])
2.2,SUM

对于mysql的求和统计操作,一般都是通过sum聚合函数实现,如查看订单表中的总价格的和

SELECT SUM(price) AS total FROM orders

在moogodb中的实现也可以如下,管道结合 $sum 操作符实现,这里和上面的一样,只是在sum求和时携带的参数不一样,上面的值设置的是1,下面的值设置的是每条文档中具体的某个字段的值,因此可以统计出所有订单的汇总价格

db.orders.aggregate([{$group:{_id:null,total:{$sum:"$price"}}}   
])
2.3,Group By

在上面虽然也用了group by,但是在 _id 那个字段并没有设置对应文档中的字段,在实际情况看到会有根据某个字段先分组早再求和的情况,如根据用户id进行分组再进行求和

select user_id,sum(price) as total from orders group by user_id

结合上面的1,2两点,可以得知上面的mysql的效果实现如下,让_id 字段设置成要分组的字段即可

db.orders.aggregate([{$group:{_id:"$user_id",total:{$sum:"price"}}}
])
2.4,分组+排序

在订单表中,要查出每一个用户下单花费的总金额,并通过从大到小的方式进行排序

select user_id,sum(price) as total from orders group by user_id order by total

mongodb的实现如下,这里需要两个聚合操作,将上一个聚合操作的结果给下一个聚合操作,在sort聚合函数中,1表示升序,2表示降序

db.orders.aggregate([{$group:{_id:"$user_id",total:{$sum,"$price"}}},{$sort:{total:1}}
])
2.5,多字段分组+时间格式化

就是需要通过user_id+每天的进行分组,统计每个用户每天消费了多少

select user_id,date_format(created_at,'%y-%m-%d') as order_date,sum(price)
from orders
group by user_id,date_formate(created_at,'%-y-%m-%d')    

mongodb的聚合操作如下,如果有多个分组字段,那么就在 _id 对象中设置多个参数,并且按照从上往下的顺序设置,使用日期表达式操作符将时间进行格式化

db.orders.aggregate([{$group:{_id:{user_id:"$user_id",order_date: { $dateToString: {format: "%Y-%m-%d",date: "$created_at"}}},total:{$sum:"price"}}}
])
2.6,Group By + Having

比如返回用户消费大于1000的用户信息,mysql的语法如下

select user_id,sum(price) as total from orders group by user_id having total > 1000

使用mongodb聚合操作的语法如下,通过match聚合命令匹配实现,并且结合gt的比较运算符进行数据的过滤,最后将对应的文档返回

db.orders.aggregate([{$group:{_id:"user_id",total:{$sum:"$price"}}},{$match:{total:{count:{$gt:1000}}}}
])
2.7,Where

比如返回订单表中商品id为10001的商品,并且差每个人花费的总金额,按降序排序

select user_id,sum(price)as total from orders where product_id = 10001 group by user_id order by total

使用mongodb的聚合操作的语法如下,期语法罗伊和mysql的一样,先过滤,再分组,再排序

db.orders.aggregate([{$match:{product_id:10001},$group:{_id:"$user_id",total:{$sum:"$price"}},{$sort:{total:1}}}
])
2.8,子查询

比如查询一个简单的,查询订单表中总共有多少用户下单(用户去重)

SELECTCOUNT(*)
FROM (SELECT user_id FROM orders GROUP BY user_id) t

通过mongodb举个查询的语法如下,只需要通过两个group就能实现,在第二个group中将id值设置为null

db.orders.aggregate([{$group:{_id:"$user_id",total:{$sum:"$price"}}},{$group:{_id:null,count: { $sum: 1 }}}
])
2.9,分页

在mysql中,分页查询直接通过limit即可,如查询订单表中商品id为10001的花费最多的钱10名的用户

selectuser_id,sum(price) as total
from orders
where product_id = 10001
group by user_id 
order by total desc limit 10

在mongodb的聚合管道中,其实现方式也比较简单,只需要多聚合几个条件即可,先执行where条件的管道,然后分组管道,排序管道,分页管道,最终将数据返回,通过数据库层面实现数据的过滤和查询,从而减少网络io传输

db.orders.aggregate([{$match:{product_id,10001},},{$group:{_id:"$user_id",total:{$sum:"$price"}}},{$sort:{total:-1}},{$limit:10}
])
2.10,连表查询

在mysql中,查询商品id为10001的花费最多的钱10名的用户的用户名

selectu.name,order.user_id,sum(order.price) as total
from orders order
left join user u on u.id = order.user_id
where order.product_id = 10001
group by order.user_id 
order by total desc limit 10

通过mongodb聚合渠道的方式如下,通过$lookup 关键字来实现联表,from表示需要连接的那张表,localField表示主表中需要关联的字段,foreignField表示需要关联的那张表中要关联的字段,最活通过一个 unwind 关键字将数组的值展开,让每一个订单表中查询出来的数据对应一个用户信息,最后再通过增加一个分组,排序和分页的聚合操作

db.orders.aggregate([{ $match: { product_id: 10001 } },  // 筛选出 product_id 为 10001 的订单{ $lookup: {                       // 左外连接用户表from: "users",                 // 'users' 集合(假设用户集合名称为 users)localField: "user_id",         // orders 集合中连接键foreignField: "id",            // users 集合中连接键as: "user_info"                // 查询结果的新字段名}},{ $unwind: "$user_info" },         // 展开连接结果,使每个订单对应一个用户信息{ $group: {                        // 分组操作_id: "$user_id",               // 根据 user_id 分组name: { $first: "$user_info.name" },  // 从用户信息中获取名字total: { $sum: "$price" }              // 计算总金额}},{ $sort: { total: -1 } },          // 按 total 降序排序{ $limit: 10 }                     // 限制结果为前 10 条
]);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/45888.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringCloud第三篇(服务中心与OpenFeign)

p 文章目录 一、服务中心二、Nacos注册中心 一、服务中心 在上一章我们实现了微服务拆分,并且通过Http请求实现了跨微服务的远程调用。不过这种手动发送Http请求的方式存在一些问题。 试想一下,假如商品微服务被调用较多,为了应对更高的并发…

【产品应用】一体化步进伺服电机在板材封边机中的应用

随着现代工业技术的快速发展,封边机作为木材加工行业的重要设备,其精度、效率和稳定性已成为衡量设备性能的重要指标。 近年来,一体化步进伺服电机因其高精度、高效率和强稳定性等特点,在封边机中得到了广泛应用。 本文将详细介绍…

1.5.1抽象java入门

前言: 1.5.0版本中,我们熟练使用Git三个可视化操作(签出,提交,对比),再加上1.4.0版本的新建,总计使用四个Git可视化操作;对java编程的学习,总结,…

vue 前端项目调用后端接口记录

axios中不同的类型的请求附带数据使用的关键字 请求类型关键字示例GETparamsaxios({ method: get, url: example.com, params: { key: value } })POSTdataaxios({ method: post, url: example.com, data: { key: value } })PUTdataaxios({ method: put, url: example.com, dat…

MICCAI 2024 每日一篇论文 纯纯直读 CUTS:用于多粒度无监督医学图像分割的深度学习和拓扑框架

MICCAI 2024 CUTS: A Deep Learning and Topological Framework for Multigranular Unsupervised Medical Image Segmentation CUTS: 用于多粒度无监督医学图像分割的深度学习和拓扑框架 作者 陈璐1*、Matthew Amodio1*、梁博伦.沈2、冯高3、阿曼阿维斯塔4、Sanjay Aneja3,5…

[RuoYi-Vue] - 1. 项目搭建

文章目录 🐬初始化后端项目拉取RuoYi-Vue代码Maven构建导入数据库ry-vue修改配置信息启动Redis启动项目 🌌初始化前端项目拉取RuoYi-Vue3代码项目运行成功页面 🐬初始化后端项目 拉取RuoYi-Vue代码 若依/RuoYi-Vue 代码地址 Maven构建 导入数…

7.2 AQS原理

AQS 原理 概述 全称是 AbstractQueuedSynchronizer,是阻塞式锁和相关的同步器工具的框架。 特点: 用 state 属性来表示资源的状态(分独占模式和共享模式),子类需要定义如何维护这个状态,控制如何获取锁和…

three.js官方案例(animation / skinning / ik)webgl_animation_skinning_ik.html学习记录

目录 1 WebGLCubeRenderTarget 2 TransformControls 3 CCDIKSolver 4 CCDIKHelper 4 全部脚本 1 WebGLCubeRenderTarget 球体亮 //WebGLCubeRenderTarget(size : Number, options : Object) //size - the size, in pixels. Default is 1. //options - (可选)一个保存…

软件设计之Java入门视频(15)

软件设计之Java入门视频(15) 视频教程来自B站尚硅谷: 尚硅谷Java入门视频教程,宋红康java基础视频 相关文件资料(百度网盘) 提取密码:8op3 idea 下载可以关注 软件管家 公众号 学习内容: 该视频共分为1-7…

Linux桌面溯源

X窗口系统(X Window System) Linux起源于X窗口系统(X Window System),亦即常说的X11,因其版本止于11之故。 X窗口系统(X Window System,也常称为X11或X)是一种以位图方式显示的软件窗口系统。…

zabbix 7.0 SNMP Hex数据预处理新功能

一、简介 zabbix7.0新特性是监控项新增支持SNMP Hex数据预处理。其中内置了对snmp请求结果Hex转换处理,不再需要使用繁琐的方式,如javascript脚本、替换、修整等方式处理将监控项取值做可视化处理,大福提升SNMP采集获取到Hex数据的处理效率。…

浅析 VO、DTO、DO、PO 的概念

文章目录 I 浅析 VO、DTO、DO、PO1.1 概念1.2 模型1.3 VO与DTO的区别I 浅析 VO、DTO、DO、PO 1.1 概念 VO(View Object) 视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。DTO(Data Transfer Object): 数据传输对象,这个概念来源于J2EE的设…

【C++】优先级队列(底层代码解释)

一. 定义 优先级队列是一个容器适配器,他可以根据不同的需求采用不同的容器来实现这个数据结构,优先级队列采用了堆的数据结构,默认使用vector作为容器,且采用大堆的结构进行存储数据。 (1)在第一个构造函数…

Qt之元对象系统

Qt的元对象系统提供了信号和槽机制(用于对象间的通信)、运行时类型信息和动态属性系统。 元对象系统基于三个要素: 1、QObject类为那些可以利用元对象系统的对象提供了一个基类。 2、在类声明中使用Q_OBJECT宏用于启用元对象特性&#xff0c…

项目收获总结--本地缓存方案选型及使用缓存的坑

本地缓存方案选型及使用缓存的坑 一、摘要二、本地缓存三、本地缓存实现方案3.1 自己编程实现一个缓存3.2 基于 Guava Cache 实现本地缓存3.3 基于 Caffeine 实现本地缓存3.4 基于 Encache 实现本地缓存3.5 小结 四、使用缓存的坑4.1 缓存穿透4.2 缓存击穿4.3 缓存雪崩4.4 数据…

如何管理好【管理层】?

如何管理好管理层? 现在流行“找客户痛点,不如找领导G点” 管理好管理层比管理好员工更重要,不要让管理层成为传话筒。你是抱着很大期望提供优厚的待遇聘用管理层,对于所有人来说,你需要一个这样的职位,对于他需要一分工作而已。出色的管理层就像出色的员工一样非常难寻…

leetcode日记(38)字母异位词分组

最开始的想法是创建vector<vector<string>> result&#xff0c;然后遍历strs中字符串&#xff0c;遍历result中vector&#xff0c;比较vector中第一个string和strs中string&#xff0c;若为字母异位词&#xff0c;则加入vector&#xff0c;若无&#xff0c;则创建新…

新手-前端生态

文章目录 新手的前端生态一、概念的理解1、脚手架2、组件 二、基础知识1、HTML2、css3、JavaScript 三、主流框架vue3框架 四、 工具&#xff08;特定框架&#xff09;1、uinapp 五、组件库&#xff08;&#xff09;1、uView如何在哪项目中导入uView 六、应用&#xff08;各种应…

Vulnhub靶场 | DC系列 - DC2

目录 环境搭建渗透测试 环境搭建 靶机镜像下载地址&#xff1a;https://vulnhub.com/entry/dc-2,311/需要将靶机和 kali 攻击机放在同一个局域网里&#xff1b;本实验kali 的 IP 地址&#xff1a;192.168.10.146。 渗透测试 使用 nmap 扫描 192.168.10.0/24 网段存活主机 …

2024年辽宁省数学建模竞赛C题超详细解题思路+问题一案代码分享

本文将为大家带来2024年C题超详细解题思路&#xff0c;本次竞赛6000人参加&#xff0c;共计2400队伍。C题作为本次竞赛中最简单的一道题目&#xff0c;意味着选题人数也将是最多的。因此&#xff0c;本文将对C题的解题思路以及将要面对的问题&#xff0c;进行详细的说明。希望我…