【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://xiahunao.cn/news/3248786.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【Springboot】新增profile环境配置应用启动失败

RT 最近接手了一个新的项目,为了不污染别人的环境,我新增了一个自己的环境配置。结果,在启动的时候总是失败,就算是反复mvn clean install也是无效。 问题现象 卡住无法进行下一步 解决思路 由于之前都是能启动的&#xff0c…

视频素材网站无水印的有哪些?热门视频素材网站分享

当我们走进视频创作的精彩世界时,一个难题常常摆在面前——那些高品质、无水印的视频素材究竟应该在哪里寻找?许多视频创作者感叹,寻找理想的视频素材难度甚至超过了寻找伴侣!但不用担心,今天我将为您介绍几个优质的视…

宝塔安装RabbitMq教程

需要放开15672端口,默认账号密码为guest/guest

浅说区间dp(下)

文章目录 环形区间dp例题[NOI1995] 石子合并题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示思路 [NOIP2006 提高组] 能量项链题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示思路 [NOIP2001 提高组] 数的划分题目描述输入格式输出格式样例 #1样例输…

车载音视频App框架设计

简介 统一播放器提供媒体播放一致性的交互和视觉体验,减少各个媒体应用和场景独自开发的重复工作量,实现媒体播放链路的一致性,减少碎片化的Bug。本文面向应用开发者介绍如何快速接入媒体播放器。 主要功能: 新设计的统一播放U…

进程空间的回收以及执行当前进程空间内的另一进程

1.进程的退出 1.exit 功能: 让进程退出,并刷新缓存区 参数: status:进程退出的状态 返回值: 缺省 exit -> 刷新缓存区 -> atexit注册的退出函数 -> _exit 2._exit 功能: 让进程退出,不刷…

代码随想录——分割等和子集(Leetcode LCR 101)

题目链接 0-1背包问题 class Solution {public boolean canPartition(int[] nums) {int[] dp new int[10000];int sum 0;// 首先求背包体积应该为nums数组总和的一半for(int i 0; i < nums.length; i){sum nums[i];}// 如果总和为奇数则不存在等和子集if(sum % 2 1)…

输出调节求解跟踪问题(二阶线性系统)

本文研究了一种基于增广系统的领导者-跟随者控制框架&#xff0c;旨在实现跟随者系统对领导者参考信号的精确跟踪。首先&#xff0c;建立了跟随者和领导者的独立状态空间方程&#xff0c;分别描述了它们的动态行为和输出关系。随后&#xff0c;通过将两者的状态空间方程结合成增…

在Linux系统安装MySQL有多简单

MySQL 是一种流行的开源关系数据库管理系统&#xff0c;广泛应用于各种类型的应用程序和服务。在安装TitanIDE​​​​​​​以后是没有MySQL服务的&#xff0c;我们需要单独安装安装MySQL。本文将介绍在 Linux 上安装 MySQL 的多种方式&#xff0c;包括离线安装、使用 Docker …

el-tree动态添加子节点的问题

如果我们需要动态往el-tree里面某一个节点添加子节点&#xff0c;追加或删除&#xff0c;我跟你讲&#xff0c;一定要显式地调用el-tree的方法&#xff0c;不然的话&#xff0c;后面调用setChecked这种方法看不到效果的。 比如el-tree绑定的data如下&#xff1a; [{id:"1…

DP(1500-1700)(刷题)

1.状态机模型&#xff1a;https://codeforces.com/contest/1984/problem/C2 记一下max与min状态转移即可&#xff0c;下面是AC代码&#xff1a; #include<bits/stdc.h> using namespace std; typedef long long ll; ll a[200010],t,n; ll dp[200010][2];//dp[i][0]表示…

掌握这些技巧,让你成为画册制作高手

在数字化的时代背景下&#xff0c;电子画册以其便捷的传播方式、丰富的视觉表现形式&#xff0c;赢得了大众的喜爱。它不仅能够在个人电脑上展现&#xff0c;还能通过智能手机、平板电脑等多种移动设备随时随地被访问和浏览。这种跨平台的支持&#xff0c;使得无论你身处何地&a…

volatile关键字解析

一、volatile介绍 volatile是Java提供的一种轻量级的同步机制&#xff0c;在并发编程中&#xff0c;它也扮演着比较重要的角色。同synchronized相比&#xff08;synchronized通常称为重量级锁&#xff09;&#xff0c;volatile更轻量级&#xff0c;相比使用synchronized所带来的…

leetcode热题100.分割等和子集(动态规划)

分割等和子集 Problem: 416. 分割等和子集 思路 我选择使用动态规划的方法来解题。我们需要判断是否可以将数组分割成两个子集&#xff0c;使得这两个子集的和相等。这个问题可以转化为在数组中找到一个子集&#xff0c;使得其和等于数组总和的一半。 解题过程 首先&#xf…

【Django】网上蛋糕商城后台-商品管理

1.商品管理功能 当管理员点击商品管理时&#xff0c;发送服务器请求 path(admin/goods_list/, viewsAdmin.goods_list), # 处理商品列表请求 def goods_list(request):try:type request.GET["type"]except:type 0try:ym request.GET["ym"]except:ym …

5大常用的回归测试工具介绍

回归测试工具介绍 以下是一些可用于创建和执行回归测试的工具。但是&#xff0c;在决定使用哪些产品之前&#xff0c;应彻底研究每种产品的要求。 Selenium Selenium 是一个开源 Web 自动化测试工具&#xff0c;用于测试网站和 Web 应用程序。它被认为是用于Web 应用程序测试的…

路径规划 | 基于DQN深度强化学习算法的路径规划(Matlab)

目录 效果一览基本介绍程序设计参考文献 效果一览 基本介绍 DQN路径规划算法 基于深度强化学习算法的路径规划 matlab2023b 栅格环境&#xff0c;走迷宫&#xff0c;可以通过窗口界面方便观察交互过程&#xff0c;代码注释详尽。 程序设计 完整源码和数据私信博主回复基于DQN深…

【Linux信号】信号的保存、信号在内核中的表示、信号集操作函数、sigprocmask、sigpending

目录 信号在内核中的表示信号阻塞的理解 sigset_t 信号集操作函数 sigprocmask sigpending sigprocmask和sigpending都是系统调用 我们先来了解一下关于信号的一些常见概念&#xff1a; 实际执行 信号的处理动作 称为信号递达。 信号从产生到递达的之间的状态称为信号未决…

场外个股期权交割日是每个月几号?怎么参与场外个股期权?

今天带你了解场外个股期权交割日是每个月几号&#xff1f;怎么参与场外个股期权&#xff1f;在进行期权交易之前&#xff0c;投资者需要选择一个可靠的期权交易平台。 个股场外期权交易是指在股票交易所以外的场所进行的期权交易。期权是一种约定&#xff0c;根据该约定&#…

Docker网络模式和Cgroup资源限制

目录 1、Docker网络 &#xff08;1&#xff09;Docker网络实现原理 查看容器的输出和日志信息 2、Docker 的网络模式 查看docker列表 &#xff08;1&#xff09;网络模式详解 1&#xff09;host模式 2&#xff09;container模式 3&#xff09;none模式 4&#xff09;br…