MongoDB-aggregate流式计算:带条件的关联查询使用案例分析
在数据库的查询中,是一定会遇到表关联查询的。当两张大表关联时,时常会遇到性能和资源问题。这篇文章就是用一个例子来分享MongoDB带条件的关联查询发挥的作用。
假设工作环境中有两张MongoDB集合:SC_DATA(学生基本信息集合)、DICT_DATA(值域字典集合),集合结构如下:
| SC_DATA | |
| uniqueid | 学生唯一号 |
| sfzid | 学生身份证 |
| xsxm | 学生姓名 |
| mz | 民族 |
| xb | 性别 |
| DICT_DATA | |
| clss | 字典类别 |
| value | 字典值域 |
| map | 字典值域映射值 |
| version | 字典版本 |
现在分别给这两张表插入一些测试数据,给SC_DATA插入10条数据,给DICT_DATA插入6条数据
db.SC_DATA.insertMany([{ "uniqueid" : "10001", "sfzid" : "3715xxxx0813", "xsxm" :"张一","mz":"1","xb":"1" },{ "uniqueid" : "10002", "sfzid" : "3715xxxx0814", "xsxm" :"张二","mz":"1","xb":"1" },{ "uniqueid" : "10003", "sfzid" : "3715xxxx0815", "xsxm" :"张三","mz":"1","xb":"1" },{ "uniqueid" : "10004", "sfzid" : "3715xxxx0816", "xsxm" :"张四","mz":"1","xb":"b" },{ "uniqueid" : "10005", "sfzid" : "3715xxxx0817", "xsxm" :"张五","mz":"a","xb":"1" },{ "uniqueid" : "10006", "sfzid" : "3715xxxx0819", "xsxm" :"张六","mz":"1","xb":"b" },{ "uniqueid" : "10007", "sfzid" : "3715xxxx0823", "xsxm" :"张七","mz":"1","xb":"1" },{ "uniqueid" : "10008", "sfzid" : "3715xxxx0833", "xsxm" :"张八","mz":"1","xb":"1" },{ "uniqueid" : "10009", "sfzid" : "3715xxxx0843", "xsxm" :"张九","mz":"1","xb":"1" },{ "uniqueid" : "100010", "sfzid" : "3715xxxx0853", "xsxm" :"张十","mz":"1","xb":"1" },
])
db.DICT_DATA.insertMany([{ "clss" : "民族", "value" : "汉族", "map" :"1","version":"v1.0"},{ "clss" : "民族", "value" : "壮族", "map" :"2","version":"v1.0"},{ "clss" : "民族", "value" : "满族", "map" :"3","version":"v1.0"},{ "clss" : "民族", "value" : "回族", "map" :"4","version":"v1.0"},{ "clss" : "性别", "value" : "男", "map" :"1","version":"v1.0"},{ "clss" : "性别", "value" : "女", "map" :"2","version":"v1.0"}])
此时,有个需求是 “统计出SC_DATA集合中民族、性别字段在字典值域内的数据”!
一般呢,思路是利用两集合关联,过滤出能关联上的数据。MongoDB的$lookup操作符类似于关系数据库的左连接,根据当前实际情况,用大表(SC_DATA.mz、SC_DATA.xb)左连接小表(DICT_DATA.map),能关联上的数据就是SC_DATA集合中民族、性别字段在字典值域内的数据!
一般呢,就直接用了$lookup进行关联了,但是,观察下DICT_DATA字典数据,承担关联任务的字段——map,有多个相同值,必须加上clss条件过滤才能得出准确数据,代码如下。
db.SC_DATA.aggregate([{$lookup: {from: "DICT_DATA",localField: "mz",foreignField: "map",as: "DICT_DATA"}},{$unwind: {path: "$DICT_DATA",preserveNullAndEmptyArrays: true}},{$match: {"DICT_DATA.clss": "民族"}},{$group: {_id: null,count: {$sum: 1}}}])
但是,诸位请看,上面的代码是先关联,再过滤。通过compass工具分阶段查看,可以更清晰的看到关联后,因为DICT_DATA.map存在重复值,所以如果SC_DATA能和DICT_DATA关联上的话,数据会翻倍。
对于我们上面的测试数据,SC_DATA有10条测试数据,和DICT_DATA关联后数据量是19条,过滤clss后是9条。大家可能觉得这种还好,但是如果SC_DATA有上千万条数据,DICT_DATA的数据更多,重复值更多,这样关联出来的数据是非常惊人的,效率也会变得奇慢无比,甚至会造成数据库卡死。

如果能够在关联出结果前,就进行过滤,就会让更少量的数据进入到下一个MongoDB聚合管道,就会消耗更少量的资源。
这里也就引出了这篇文章的主角:带条件的$lookup,语法格式如下:
{$lookup:{from: <joined collection>,let: { <var_1>: <expression>, …, <var_n>: <expression> },pipeline: [ <pipeline to run on joined collection> ],as: <output array field>}
}
参数说明如下:
| 参数 | 说明 |
| from | 指定待执行连接操作的集合,是当前集合【可以看下面的例子理解】 |
| let | 指定各个管道阶段使用的变量,这里的变量可以放到pipeline中使用; 这里指定的都是自身当前集合中的字段变量; 这里指定变量的时候以 col_name:$col_name的形式,在pipeline中使用的时候以 $$col_name形式 使用; |
| pipeline | 1、pipeline中,可以使用let中指定的变量,也可以使用当前集合中的字段; 2、pipeline中,$match阶段需要使用$expr操作符来访问变量,$expr允许在$match中使用聚合表达式; 3、pipeline中,放置在$expr上的$eq、$lt、$lte、$gt、$gte比较操作符,可以使用$lookup阶段引用的 from集合上的索引; 3.1、使用索引的限制一:不使用多键索引; 3.2、使用索引的限制二:当操作的数量比较大,或者操作数据类型没有定义时,不使用索引; 3.3、使用索引的限制三:索引只能用于字段和常量之间的比较,变量和变量之间的比较不能使用索引; 4、pipeline中,非$match阶段,不需要使用$expr操作符来访问变量 |
| as | 指定要添加到已连接文档的新数量字段的名称。新的大量字段包含来自加入的收集的匹配文档。如果指定的名称已存在于所连接的文档中,则现有字段将被覆盖。 |
针对 “统计出SC_DATA集合中民族、性别字段在字典值域内的数据”!这个需求,我们就可以将其写为如下代码!
db.SC_DATA.aggregate([{$lookup: {from: "DICT_DATA",let: {mz: "$mz"},pipeline: [{$match: {$expr: {$and: [{$eq: ["$map", "$$mz"]},{$eq: ["$clss", "民族"]}]}}}],as: "DICT_DATA"}},{$unwind: {path: "$DICT_DATA",preserveNullAndEmptyArrays: true}},{$match: {"DICT_DATA.map": {$ne: null}}},{$group: {_id: null,count: {$sum: 1}}}])
从compass工具中,可以更清晰的看到数据量变化。此时,因为在输出关联数据前,先进行了过滤。这种写法可以消耗更少的数据库及系统资源,但在索引使用上和正常关联略有区别需要注意。

相关文章:
MongoDB-aggregate流式计算:带条件的关联查询使用案例分析
在数据库的查询中,是一定会遇到表关联查询的。当两张大表关联时,时常会遇到性能和资源问题。这篇文章就是用一个例子来分享MongoDB带条件的关联查询发挥的作用。 假设工作环境中有两张MongoDB集合:SC_DATA(学生基本信息集合&…...
Redis数据库与GO(一):安装,string,hash
安装包地址:https://github.com/tporadowski/redis/releases 建议下载zip版本,解压即可使用。解压后,依次打开目录下的redis-server.exe和redis-cli.exe,redis-cli.exe用于输入指令。 一、基本结构 如图,redis对外有个…...
expressjs,实现上传图片,返回图片链接
在 Express.js 中实现图片上传并返回图片链接,你通常需要使用一个中间件来处理文件上传,比如 multer。multer 是一个 node.js 的中间件,用于处理 multipart/form-data 类型的表单数据,主要用于上传文件。 以下是一个简单的示例&a…...
爬虫——XPath基本用法
第一章XML 一、xml简介 1.什么是XML? 1,XML指可扩展标记语言 2,XML是一种标记语言,类似于HTML 3,XML的设计宗旨是传输数据,而非显示数据 4,XML标签需要我们自己自定义 5,XML被…...
常见排序算法汇总
排序算法汇总 这篇文章说明下排序算法,直接开始。 1.冒泡排序 最简单直观的排序算法了,新手入门的第一个排序算法,也非常直观,最大的数字像泡泡一样一个个的“冒”到数组的最后面。 算法思想:反复遍历要排序的序列…...
Golang | Leetcode Golang题解之第459题重复的子字符串
题目: 题解: func repeatedSubstringPattern(s string) bool {return kmp(s s, s) }func kmp(query, pattern string) bool {n, m : len(query), len(pattern)fail : make([]int, m)for i : 0; i < m; i {fail[i] -1}for i : 1; i < m; i {j : …...
0.计网和操作系统
0.计网和操作系统 熟悉计算机网络和操作系统知识,包括 TCP/IP、UDP、HTTP、DNS 协议等。 常见的页面置换算法: 先进先出(FIFO)算法:将最早进入内存的页面替换出去。最近最少使用(LRU)算法&am…...
探索Prompt Engineering:开启大型语言模型潜力的钥匙
前言 什么是Prompt?Prompt Engineering? Prompt可以理解为向语言模型提出的问题或者指令,它是激发模型产生特定类型响应的“触发器”。 Prompt Engineering,即提示工程,是近年来随着大型语言模型(LLM,Larg…...
滚雪球学Oracle[3.3讲]:数据定义语言(DDL)
全文目录: 前言一、约束的高级使用1.1 主键(Primary Key)案例演示:定义主键 1.2 唯一性约束(Unique)案例演示:定义唯一性约束 1.3 外键(Foreign Key)案例演示:…...
ssrf学习(ctfhub靶场)
ssrf练习 目录 ssrf类型 漏洞形成原理(来自网络) 靶场题目 第一题(url探测网站下文件) 第二关(使用伪协议) 关于http和file协议的理解 file协议 http协议 第三关(端口扫描)…...
ElasticSearch之网络配置
对官方文档Networking的阅读笔记。 ES集群中的节点,支持处理两类通信平面 集群内节点之间的通信,官方文档称之为transport layer。集群外的通信,处理客户端下发的请求,比如数据的CRUD,检索等,官方文档称之…...
【C语言进阶】系统测试与调试
1. 引言 在开始本教程的深度学习之前,我们需要了解整个教程的目标及其结构,以及为何进阶学习是提升C语言技能的关键。 目标和结构: 教程目标:本教程旨在通过系统化的学习,从单元测试、系统集成测试到调试技巧…...
多个单链表的合成
建立两个非递减有序单链表,然后合并成一个非递增有序的单链表。 注意:建立非递减有序的单链表,需要采用创建单链表的算法 输入格式: 1 9 5 7 3 0 2 8 4 6 0 输出格式: 9 8 7 6 5 4 3 2 1 输入样例: 在这里给出一组输入。例如…...
『建议收藏』ChatGPT Canvas功能进阶使用指南!
大家好,我是木易,一个持续关注AI领域的互联网技术产品经理,国内Top2本科,美国Top10 CS研究生,MBA。我坚信AI是普通人变强的“外挂”,专注于分享AI全维度知识,包括但不限于AI科普,AI工…...
Ollama 运行视觉语言模型LLaVA
Ollama的LLaVA(大型语言和视觉助手)模型集已更新至 1.6 版,支持: 更高的图像分辨率:支持高达 4 倍的像素,使模型能够掌握更多细节。改进的文本识别和推理能力:在附加文档、图表和图表数据集上进…...
gdb 调试 linux 应用程序的技巧介绍
使用 gdb 来调试 Linux 应用程序时,可以显著提高开发和调试的效率。gdb(GNU 调试器)是一款功能强大的调试工具,适用于调试各类 C、C 程序。它允许我们在运行程序时检查其状态,设置断点,跟踪变量值的变化&am…...
Java项目实战II基于Java+Spring Boot+MySQL的房产销售系统(源码+数据库+文档)
目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者 一、前言 随着房地产市场的蓬勃发展,房产销售业务日益复杂,传统的手工管理方式已难以满…...
aws(学习笔记第一课) AWS CLI,创建ec2 server以及drawio进行aws画图
aws(学习笔记第一课) 使用AWS CLI 学习内容: 使用AWS CLI配置密钥对创建ec2 server使用drawio(vscode插件)进行AWS的画图 1. 使用AWS CLI 注册AWS账号 AWS是通用的云计算平台,可以提供ec2,vpc,SNS以及clo…...
【Python】Eventlet 异步网络库简介
Eventlet 是一个 Python 的异步网络库,它使用协程(green threads)来简化并发编程。通过非阻塞的 I/O 操作,Eventlet 使得你可以轻松编写高性能的网络应用程序,而无需处理复杂的回调逻辑或编写多线程代码。它广泛应用于…...
【JNI】数组的基本使用
在上一期讲了基本类型的基本使用,这期来说一说数组的基本使用 HelloJNI.java:实现myArray函数,把一个整型数组转换为双精度型数组 public class HelloJNI { static {System.loadLibrary("hello"); }private native String HelloW…...
ConvNeXt 改进 :ConvNeXt添加可变形卷积(DCNv2,CVPR 2018),实现高效涨点,二次创新CNBlock结构 ,独家首发
本文教的是方法,也给出几种改进方法,二次创新结构,百变不离其宗,一文带你改进自己模型,科研路上少走弯路。 前言 DCNv2对原始的DCNv1进行了改进,可变形卷积网络的卓越性能源于其适应对象几何变化的能力。通过对其自适应行为的检查,虽然对其神经特征的空间支持比常规的Co…...
Stable-Diffusion-v1-5-archive多风格生成效果:复古海报/科技感UI/手绘插画实拍
Stable Diffusion v1.5 Archive多风格生成效果:复古海报/科技感UI/手绘插画实拍 1. 模型介绍与核心能力 Stable Diffusion v1.5 Archive是经典SD1.5文生图模型的归档版本,作为AI图像生成领域的"常青树",它依然保持着强大的通用图…...
如何高效使用猫抓插件:浏览器资源嗅探实用指南
如何高效使用猫抓插件:浏览器资源嗅探实用指南 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 在数字化时代,我们每天浏览网…...
FUTURE POLICE语音模型Agent智能体开发:多轮语音对话任务规划
FUTURE POLICE语音模型Agent智能体开发:多轮语音对话任务规划 想象一下,你对着手机说:“帮我订一张下周五从北京飞往上海,下午出发的机票,要经济舱。” 几秒钟后,手机用自然的人声回复你:“好的…...
AI图像增强:让模糊照片重获新生的实用工具
AI图像增强:让模糊照片重获新生的实用工具 【免费下载链接】Real-ESRGAN-GUI Lovely Real-ESRGAN / Real-CUGAN GUI Wrapper 项目地址: https://gitcode.com/gh_mirrors/re/Real-ESRGAN-GUI 在数字时代,我们每个人的手机相册里都藏着珍贵的回忆—…...
OEC-turbo变废为宝:从吃灰PCDN盒子到家庭服务器,Armbian/OpenWrt刷机实战记录
OEC-turbo硬件改造指南:从闲置PCDN设备到全能家庭服务器 手上闲置的OEC-turbo盒子除了吃灰还能做什么?这款搭载RK3568芯片的设备实际上是一块被低估的硬件宝藏。相比市面上热门的斐讯N1等矿渣设备,OEC-turbo在处理器性能、内存配置和扩展性方…...
m4s-converter:打破B站缓存限制,永久保存珍贵视频内容
m4s-converter:打破B站缓存限制,永久保存珍贵视频内容 【免费下载链接】m4s-converter 一个跨平台小工具,将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 在数字内容时代&am…...
3步安装ViGEMBus虚拟手柄驱动:让Windows游戏体验全面升级
3步安装ViGEMBus虚拟手柄驱动:让Windows游戏体验全面升级 【免费下载链接】ViGEmBus Windows kernel-mode driver emulating well-known USB game controllers. 项目地址: https://gitcode.com/gh_mirrors/vi/ViGEmBus 想要在Windows系统上使用任何手柄玩游戏…...
5分钟终极指南:Windows虚拟手柄驱动ViGEmBus完整教程
5分钟终极指南:Windows虚拟手柄驱动ViGEmBus完整教程 【免费下载链接】ViGEmBus Windows kernel-mode driver emulating well-known USB game controllers. 项目地址: https://gitcode.com/gh_mirrors/vi/ViGEmBus 想要在Windows系统上享受专业级的游戏控制体…...
从‘torch not found’到成功训练:一个YOLOv8环境配置的完整避坑实录(含CUDA/cuDNN版本选择)
YOLOv8环境配置终极指南:从版本匹配到显存优化的全流程实战 在计算机视觉领域,YOLOv8作为目标检测的标杆算法,其安装配置过程却常常成为开发者的"拦路虎"。本文将带你系统解决从PyTorch版本选择、CUDA环境配置到显存优化的全链路问…...
