当前位置: 首页 > news >正文

MongoDB-集合(表)关联查询

MongoDB 可以做集合(表)关联,但和 MySQL JOIN 完全不一样

一、核心结论

  1. MongoDB支持跨集合关联查询,靠聚合管道$lookup实现,等价 SQL左外连接 LEFT JOINMongoDB。
  2. 限制:只能同库关联,不支持跨库;关联结果永远是数组,没有直接 INNER JOIN,需要手动$unwind模拟内连接。
  3. 设计理念:MongoDB 优先推荐内嵌文档,少用$lookup,多表关联性能远不如 MySQL。

二、$lookup 两种用法完整示例

前置测试数据

集合 1:users用户

db.users.insertMany([ {_id: ObjectId("600001"), name:"张三", phone:"13800011111"}, {_id: ObjectId("600002"), name:"李四", phone:"13800022222"} ])

集合 2:orders订单(存 userId 关联用户)

db.orders.insertMany([ {_id:1001, userId:ObjectId("600001"), amount:99, createTime:ISODate()}, {_id:1002, userId:ObjectId("600001"), amount:199, createTime:ISODate()}, {_id:1003, userId:ObjectId("600003"), amount:59, createTime:ISODate()} ])

1)基础等值 $lookup(简单左连接)

语法

{ $lookup:{ from: "关联集合名", localField: "当前集合关联字段", foreignField: "关联集合匹配字段", as: "存放匹配结果的数组字段名" } }

查询:查订单,带出对应用户信息

db.orders.aggregate([ // 先过滤订单(可选,提前缩小数据量提升性能) {$match: {amount: {$gte: 50}}}, // 关联用户表 { $lookup:{ from:"users", localField:"userId", foreignField:"_id", as:"userList" // 匹配到的用户会存在数组里,无匹配则为空数组 [] } } ])

返回结果结构:

{ "_id":1001, "userId":ObjectId("600001"), "amount":99, "userList":[{_id:ObjectId("600001"), name:"张三", phone:"13800011111"}] }, { "_id":1003, "userId":ObjectId("600003"), "amount":59, "userList":[] // 无匹配用户,数组空 }

模拟 INNER JOIN(只保留有匹配的数据)

$unwind拆解数组,空数组会直接过滤掉:

db.orders.aggregate([ {$lookup:{from:"users",localField:"userId",foreignField:"_id",as:"userList"}}, {$unwind:"$userList"}, // 拆解数组,空数组文档直接丢弃 {$project:{ // 自定义返回字段 orderId:"$_id", amount:1, userName:"$userList.name", userPhone:"$userList.phone" }} ])

2)高级带管道 $lookup(复杂条件关联,3.6 + 支持)

基础$lookup只能等值匹配;带pipeline可以做不等值、多条件、过滤、投影。 场景:关联用户时只返回姓名,并且过滤手机号不为空的用户

db.orders.aggregate([ { $lookup:{ from:"users", let:{uid:"$userId"}, // 定义变量,当前文档字段 pipeline:[ {$match:{ $expr:{ $and:[ {$eq:["$_id","$$uid"]}, // 关联匹配 {$ne:["$phone",null]} // 附加过滤条件 ] } }}, {$project:{name:1,_id:0}} // 只返回name字段 ], as:"userInfo" } } ])

三、多集合连续关联(三表联查)

订单 → 用户 → 商品

db.orders.aggregate([ // 关联用户 {$lookup:{from:"users",localField:"userId",foreignField:"_id",as:"user"}}, {$unwind:"$user"}, // 再关联商品 {$lookup:{from:"goods",localField:"goodsId",foreignField:"_id",as:"goods"}}, {$unwind:"$goods"} ])

四、$lookup 和 MySQL JOIN 关键区别

对比项MySQL JOINMongoDB $lookup
连接类型INNER/LEFT/RIGHT/FULL仅原生左外连接,INNER 需手动 $unwind
返回结构行扁平化匹配数据封装成数组,需 $unwind 摊平
关联条件等值、不等值、多条件直接写基础版仅等值;复杂条件必须 pipeline
跨库支持不支持,只能同数据库集合关联
性能JOIN 有优化器、索引友好大量 $lookup 性能差,分片环境开销更高
外键约束支持物理外键无外键,关联靠业务 ID 手动维护

五、MongoDB 两种关联模型(最佳实践)

方案 1:内嵌文档(优先推荐,完全不用 $lookup)

适合一对一、少量关联数据,查询一次拿到全部信息,无联表开销

// 订单直接内嵌用户简化信息 { _id:1001, amount:99, user:{name:"张三", phone:"13800011111"} }

方案 2:引用 + $lookup(适合一对多、数据量大)

用户独立集合,订单存 userId,查询时用$lookup关联; 缺点:聚合查询变慢,分页、过滤逻辑复杂。

六、使用踩坑与性能优化

  1. 关联字段必须建索引foreignField(如 users._id 自带索引,自定义字段要手动创建)
  2. $match$lookup:提前过滤数据,减少关联扫描行数
  3. 大集合避免多层连续$lookup,会严重拖慢查询
  4. 一对一场景用$unwind摊平数组,简化返回结构
  5. 不要用$lookup做高频分页查询,优先内嵌设计

七、一句话总结

MongoDB 通过聚合$lookup实现集合关联,等价左连接,但性能弱于 MySQL JOIN;业务设计优先内嵌文档减少联表,实在需要拆分集合再使用引用 +$lookup

http://www.cnnetsun.cn/news/3211766.html

相关文章:

  • 【OpenHarmony/HarmonyOs 】化学学习 App 收藏夹功能实践:AppStorage 本地持久化与响应式刷新
  • 音视频编解码:VP8 / VP9 / H.264 / Opus
  • 2026降AIGC革命:AI率92%暴降至5%!实测10款AI智能降重工具!10款工具深度解析!
  • 3分钟搞定网易云插件安装:BetterNCM-Installer终极解决方案
  • spring通过方法注入,针对多实例的Bean
  • 2026年7月探寻四川信誉优良的GEO优化运营商
  • AutoJS6 + Shizuku 实战:淘金币自动签到与任务脚本
  • 如何一次性解决所有Visual C++运行库问题:终极AIO安装指南
  • Typeahead 2.0 智能搜索体验升级实战
  • 阿里面试:如果Agent 挂100个 Skill ,如何提升召回率、准确度、F1综合值?尼恩 《Skills调优圣经》,来一次 泰山压顶 式的 降维打击
  • rust 学习 闭包
  • 第4章:Linux系统重点复习
  • AI 看不懂老项目?先用“项目说明书 + 目录树”把上下文交给它
  • [特殊字符]《京东宙斯迁移公告解读:老接口 360buy.ware.get→ jingdong.ware.read.get平滑切换(附Python源码)》
  • 从零搭建工业物联网监控大屏:Node-RED + 有人云 零代码方案
  • HRD进化论04讲:战略解码
  • PostgreSQL高级特性应用
  • PyTorch DDP 多机多卡配置:2节点8卡集群部署与通信瓶颈分析
  • Models-学习指南_小白版
  • Mermaid终极指南:用代码快速创建专业图表,彻底告别文档滞后问题
  • Windows 证书管理:3种存储位置(个人/根/中间)的导入策略与安全影响
  • AD7175-8与PIC18F4610高精度信号采集方案解析
  • 2026年AI写作辅助平台实测认证:5款神器从文献到降重一站式避坑指南
  • 15个实用的代码审查工具,自动化检查
  • 如何快速精通猫抓资源嗅探:进阶用户终极配置指南
  • 15个实用的代码版本控制工具,Git替代品
  • 《B4071 [GESP202412 五级] 武器强化》
  • GHelper终极指南:轻松掌控华硕笔记本性能的轻量级神器
  • 兰州兰银官话语义角色标注数据采集公司
  • FFmpeg 入门:命令行的 20 个常用场景