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

MongoDB(45) 嵌入式文档与引用的优缺点是什么?

嵌入式文档(Embedded Documents)和引用(References)是MongoDB中常用的两种数据建模方式,它们各有优缺点。选择使用哪种方式取决于具体的应用场景和需求。

嵌入式文档

优点
  1. 读取效率高:嵌入式文档通常可以在一次查询中获取所有相关数据,减少了数据库查询次数。
  2. 事务一致性:由于所有相关数据都在同一个文档中,更新时可以保证数据的一致性,不需要担心分布式事务问题。
  3. 简单性:数据模型简单,查询和处理方便。
缺点
  1. 文档大小限制:MongoDB文档大小限制为16MB,嵌入式文档如果过大,可能会超过这个限制。
  2. 冗余数据:在一些场景下,嵌入式文档会导致数据冗余,增加存储空间。
  3. 更新效率低:如果嵌入的数据结构复杂,更新可能会变得比较繁琐和低效。

引用

优点
  1. 数据去重:引用方式将数据分离到不同的集合中,减少了数据冗余。
  2. 灵活性高:各个集合独立更新,灵活性更高,适合复杂的数据模型。
  3. 文档大小分离:因为数据被分离到不同的文档中,不会受到单个文档大小的限制。
缺点
  1. 查询效率低:需要多次查询才能获取所有相关数据,特别是在大数据量下查询效率可能较低。
  2. 事务一致性差:跨集合的更新操作不能保证原子性,需要额外处理事务一致性问题。
  3. 复杂性高:数据模型复杂,需要处理数据的关联和联合查询。

使用示例

以下示例展示了在Node.js中如何使用嵌入式文档和引用,并对比它们的优缺点。

安装MongoDB的Node.js驱动
npminstallmongodb
嵌入式文档示例
插入数据
const{MongoClient}=require('mongodb');asyncfunctioninsertEmbeddedData(){consturi="mongodb://localhost:27017";constclient=newMongoClient(uri,{useUnifiedTopology:true});try{awaitclient.connect();constdb=client.db('myDatabase');constusersCollection=db.collection('users');awaitusersCollection.deleteMany({});// 清空集合awaitusersCollection.insertMany([{userId:1,name:"Alice",address:{street:"123 Main St",city:"New York",state:"NY",zip:"10001"},orders:[{orderId:101,amount:50.5,date:newDate("2022-01-01")},{orderId:102,amount:100.0,date:newDate("2022-02-01")}]},{userId:2,name:"Bob",address:{street:"456 Maple Ave",city:"San Francisco",state:"CA",zip:"94101"},orders:[{orderId:103,amount:75.0,date:newDate("2022-01-15")},{orderId:104,amount:200.0,date:newDate("2022-03-01")}]}]);console.log("Embedded data inserted");}finally{awaitclient.close();}}insertEmbeddedData().catch(console.error);
查询数据
asyncfunctionqueryEmbeddedData(){consturi="mongodb://localhost:27017";constclient=newMongoClient(uri,{useUnifiedTopology:true});try{awaitclient.connect();constdb=client.db('myDatabase');constusersCollection=db.collection('users');// 查询某个用户及其所有订单console.log("\nQuery a user and their orders:");letuser=awaitusersCollection.findOne({name:"Alice"});console.log(user);}finally{awaitclient.close();}}queryEmbeddedData().catch(console.error);

嵌入式文档的查询效率很高,因为所有数据都在同一个文档中。

引用示例
插入数据
const{MongoClient,ObjectId}=require('mongodb');asyncfunctioninsertReferencedData(){consturi="mongodb://localhost:27017";constclient=newMongoClient(uri,{useUnifiedTopology:true});try{awaitclient.connect();constdb=client.db('myDatabase');constusersCollection=db.collection('users');constordersCollection=db.collection('orders');awaitusersCollection.deleteMany({});// 清空用户集合awaitordersCollection.deleteMany({});// 清空订单集合// 插入用户数据constusers=awaitusersCollection.insertMany([{name:"Alice"},{name:"Bob"}]);// 插入订单数据,并使用用户的ObjectId作为引用awaitordersCollection.insertMany([{userId:users.insertedIds[0],amount:50.5,date:newDate("2022-01-01")},{userId:users.insertedIds[0],amount:100.0,date:newDate("2022-02-01")},{userId:users.insertedIds[1],amount:75.0,date:newDate("2022-01-15")},{userId:users.insertedIds[1],amount:200.0,date:newDate("2022-03-01")}]);console.log("Referenced data inserted");}finally{awaitclient.close();}}insertReferencedData().catch(console.error);
查询数据
asyncfunctionqueryReferencedData(){consturi="mongodb://localhost:27017";constclient=newMongoClient(uri,{useUnifiedTopology:true});try{awaitclient.connect();constdb=client.db('myDatabase');constusersCollection=db.collection('users');constordersCollection=db.collection('orders');// 查询某个用户及其所有订单console.log("\nQuery a user and their orders:");letuser=awaitusersCollection.findOne({name:"Alice"});letorders=awaitordersCollection.find({userId:user._id}).toArray();console.log({user,orders});// 查询所有订单及其对应的用户信息console.log("\nQuery all orders and their corresponding users:");letresults=awaitordersCollection.aggregate([{$lookup:{from:'users',// 要关联的集合localField:'userId',// orders 集合中的字段foreignField:'_id',// users 集合中的字段as:'user'// 输出数组字段}},{$unwind:'$user'// 展开数组}]).toArray();console.log(results);}finally{awaitclient.close();}}queryReferencedData().catch(console.error);

通过这些示例,我们可以看到两种数据建模方式在操作上的不同:

  1. 嵌入式文档适用于小型数据集和简单的数据关系,读取效率高,数据一致性好,但是在数据量大或者关系复杂的情况下会导致文档过大,更新效率低。

  2. 引用适用于大型数据集和复杂的数据关系,数据去重和独立更新灵活,但查询效率低,特别是在需要多次查询获取相关数据时。此外,跨集合的事务一致性需要额外处理。

选择合适的数据建模方式取决于具体的应用场景和需求。对于一些应用,可以混合使用这两种方式,结合它们的优点,达到最佳的性能和灵活性。

http://www.jsqmd.com/news/494753/

相关文章:

  • 解决!expandable-recycler-view 已废弃,替代方案与迁移指南全解析
  • 2023年 beagle bone black教程5-CAN的使用
  • iOS App技术支持网址(URL)
  • 2026年口碑好的小程序开发品牌推荐:辽宁小程序开发/大连小程序开发综合评价公司 - 行业平台推荐
  • Next.js 13/14页面加载优化:NextTopLoader与nprogress深度整合
  • NaughtyKeyboard 使用指南
  • 国内CA服务介绍
  • 2026年比较好的威海隐形车衣品牌推荐:威海隐形车衣材质/威海隐形车衣防剐蹭/威海隐形车衣包工包料优质供应商推荐 - 行业平台推荐
  • SQL Server2022 Express和SSMS下载安装教程(超详细)
  • CTF做题笔记--[极客大挑战 2019]Upload1
  • micro-lisp 项目使用教程
  • 基于编队领航跟随+人工势场法避障的多智能体编队动态避障、集结和保持队形控制Matlab程序
  • Swot学术域名验证工具:从安装到实战的终极教程
  • 津门就医添帮手!天津陪诊行业迎新标杆,守嘉陪诊暖心落地便民惠民 - 品牌排行榜单
  • 无人船路径跟踪+NMPC非线性模型预测控制mmg模型程序、附参考文献
  • 2026年热门的轴承铜套公司推荐:由沟铜套/法兰铜套/法兰石墨铜套精选厂家 - 行业平台推荐
  • Lunar 开源项目教程
  • 简易CPU设计入门:内存读写(五)
  • 2026年热门的球面轴承品牌推荐:滑动轴承/自润滑轴承/石墨镶嵌轴承公司口碑推荐 - 行业平台推荐
  • Beagle 开源项目教程
  • Stork Oracle自动验证机器人技术解析
  • ARM64架构手动编译libtorch,安装MKL/oneDNN加速模型推理,详细流程!
  • Flow3自动化任务机器人技术解析与实现方案
  • 【亲测免费】 IBAN.js - 国际银行账号验证与格式化工具
  • 2026年质量好的防爆喷漆柜品牌推荐:环保喷漆柜实力工厂推荐 - 行业平台推荐
  • 0318晨间日记
  • Sowing Taker Auto Bot:自动化耕作协议的智能解决方案
  • Lunar 开源项目使用教程
  • go-wkhtmltopdf在AWS Lambda中的应用:无服务器PDF生成方案
  • 2026年质量好的定制喷粉房品牌推荐:工业喷粉房/大旋风喷粉房直销厂家推荐 - 行业平台推荐