MongoDB(45) 嵌入式文档与引用的优缺点是什么?
嵌入式文档Embedded Documents和引用References是MongoDB中常用的两种数据建模方式它们各有优缺点。选择使用哪种方式取决于具体的应用场景和需求。嵌入式文档优点读取效率高嵌入式文档通常可以在一次查询中获取所有相关数据减少了数据库查询次数。事务一致性由于所有相关数据都在同一个文档中更新时可以保证数据的一致性不需要担心分布式事务问题。简单性数据模型简单查询和处理方便。缺点文档大小限制MongoDB文档大小限制为16MB嵌入式文档如果过大可能会超过这个限制。冗余数据在一些场景下嵌入式文档会导致数据冗余增加存储空间。更新效率低如果嵌入的数据结构复杂更新可能会变得比较繁琐和低效。引用优点数据去重引用方式将数据分离到不同的集合中减少了数据冗余。灵活性高各个集合独立更新灵活性更高适合复杂的数据模型。文档大小分离因为数据被分离到不同的文档中不会受到单个文档大小的限制。缺点查询效率低需要多次查询才能获取所有相关数据特别是在大数据量下查询效率可能较低。事务一致性差跨集合的更新操作不能保证原子性需要额外处理事务一致性问题。复杂性高数据模型复杂需要处理数据的关联和联合查询。使用示例以下示例展示了在Node.js中如何使用嵌入式文档和引用并对比它们的优缺点。安装MongoDB的Node.js驱动npminstallmongodb嵌入式文档示例插入数据const{MongoClient}require(mongodb);asyncfunctioninsertEmbeddedData(){consturimongodb://localhost:27017;constclientnewMongoClient(uri,{useUnifiedTopology:true});try{awaitclient.connect();constdbclient.db(myDatabase);constusersCollectiondb.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(){consturimongodb://localhost:27017;constclientnewMongoClient(uri,{useUnifiedTopology:true});try{awaitclient.connect();constdbclient.db(myDatabase);constusersCollectiondb.collection(users);// 查询某个用户及其所有订单console.log(\nQuery a user and their orders:);letuserawaitusersCollection.findOne({name:Alice});console.log(user);}finally{awaitclient.close();}}queryEmbeddedData().catch(console.error);嵌入式文档的查询效率很高因为所有数据都在同一个文档中。引用示例插入数据const{MongoClient,ObjectId}require(mongodb);asyncfunctioninsertReferencedData(){consturimongodb://localhost:27017;constclientnewMongoClient(uri,{useUnifiedTopology:true});try{awaitclient.connect();constdbclient.db(myDatabase);constusersCollectiondb.collection(users);constordersCollectiondb.collection(orders);awaitusersCollection.deleteMany({});// 清空用户集合awaitordersCollection.deleteMany({});// 清空订单集合// 插入用户数据constusersawaitusersCollection.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(){consturimongodb://localhost:27017;constclientnewMongoClient(uri,{useUnifiedTopology:true});try{awaitclient.connect();constdbclient.db(myDatabase);constusersCollectiondb.collection(users);constordersCollectiondb.collection(orders);// 查询某个用户及其所有订单console.log(\nQuery a user and their orders:);letuserawaitusersCollection.findOne({name:Alice});letordersawaitordersCollection.find({userId:user._id}).toArray();console.log({user,orders});// 查询所有订单及其对应的用户信息console.log(\nQuery all orders and their corresponding users:);letresultsawaitordersCollection.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);通过这些示例我们可以看到两种数据建模方式在操作上的不同嵌入式文档适用于小型数据集和简单的数据关系读取效率高数据一致性好但是在数据量大或者关系复杂的情况下会导致文档过大更新效率低。引用适用于大型数据集和复杂的数据关系数据去重和独立更新灵活但查询效率低特别是在需要多次查询获取相关数据时。此外跨集合的事务一致性需要额外处理。选择合适的数据建模方式取决于具体的应用场景和需求。对于一些应用可以混合使用这两种方式结合它们的优点达到最佳的性能和灵活性。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2422162.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!