mongodb多表联查 mongoose多表关联
本教程详细阐述了在 Mongoose 中如何高效管理多个 MongoDB 数据库连接对应其模型。我们将深入探讨使用 mongoose.createConnection 建立独立连接的方法,以及如何正确地为每个连接、定义实例化和操作其特定模型,避免常见的模型构造函数错误,确保数据操作的准确性和隔离性。Mongoose多连接机制概述
在复杂的应用场景中,我们可能需要连接到多个mongodb数据库,例如,一个用于主业务数据,另一个用于日志或用户配置。mongoose提供了灵活的机制来管理这些独立的数据库连接。
Mongoose主要有两种建立连接的方式:mongoose.connect():这是最常用的方法,用于建立应用的默认连接。通常在应用启动时调用一次。通过此方法创建的模型,消耗显式指定连接,将自动关联到这个默认连接。mongoose.createConnection():此方法返回一个新的、独立的连接实例。它非常适合需要同时管理多个数据库连接的场景。通过createConnection 获得的每个实例连接都是独立的,拥有自己的连接池和状态。
理解这两种连接方式的区别至关重要。当您使用createConnection创建一个新连接时,您此时连接定义上的所有模型都将专门绑定到该连接实例,从而实现数据操作的隔离性。建立独立数据库连接
使用mongoose.createConnection()是建立独立数据库连接的核心。它接受与mongoose.connect()相同的连接字符串和选项对象。
const mongoose = require('mongoose');// 定义通用的连接选项,确保连接的稳定性和兼容性 const connectionOptions = { useCreateIndex: true, //确保创建索引时兼容性 useNewUrlParser: true, //新使用的URL解析器 useUnifiedTopology: true, // 使用新的统一拓扑引擎 useFindAndModify: false // 取消findAndModify(),使用findOneAndUpdate() 或findOneAndRemove()};//建立第一个数据库连接(例如,主数据库)const dbMain = mongoose.createConnection(quot;mongodb://localhost/db_mainquot;,connectionOptions);//监听连接事件,便于了解连接状态dbMain.on('connected', () =gt; { console.log('成功连接到主数据库: db_main');});dbMain.on('error', (err) =gt; { console.error('主数据库连接错误:', err);});dbMain.on('disconnected', () =gt; { console.log('主数据库连接已断开: db_main');});//建立第二个数据库连接(例如,db_en 数据库)const dbEn = mongoose.createConnection(quot;mongodb://localhost/db_enquot;,connectionOptions);dbEn.on('connected', () =gt; { console.log('成功连接到第二数据库: db_en');});dbEn.on('error', (err) =gt; { console.error('第二数据库连接错误:', err);});dbEn.on('disconnected', () =gt; { console.log('第二数据库连接已断开: db_en');});//您可以根据需要建立更多的连接登录后复制为特定的连接定义并获取模型
一旦建立了独立的连接实例(例如 dbEn),您就可以在该连接上定义和使用模型。关键是使用 connection.model() 方法。该方法的作用是:如果模型尚未定义,它会使用提供的 Schema 定义一个新的模型,并将其绑定到当前的连接实例。如果模型已经定义,会返回该连接上已定义的模型构造函数。
重要提示:connection.model(name, schema)方法的返回值是该模型的一个构造函数。您必须将此返回值然后赋给一个变量,通过这个变量来实例化模型。直接尝试新的connection.ModelName()是错误的,因为connection.ModelName还不是一个可用的属性。
让我们通过一个例子来理解这一点,并解释了常见的错误://定义一个SchemaconstpriceSchema = new mongoose.Schema({fixed:{1:{type:Number,default:199},3:{type:Number,default:499},6:{type:Number,default:729},12:{type:Number,default:999} }});// 在 dbEn 连接上定义的价格模型 // 正确的做法:将 dbEn.model() 的返回值赋给一个变量 const PriceModelEn = dbEn.model('Price',priceSchema);// 错误示范:直接尝试从连接对象访问模型,会导致 TypeError// dbEn.model('Price',priceSchema); // 此时模型已在 dbEn 上定义,但没有赋值给变量// const ggg = new dbEn.Price(); // 错误!dbEn.Price 不存在,dbEn 实例上没有名为 Price 的属性// 错误信息:TypeError: conn.Price is not a constructor 登录后
错误分析:原始问题中出现的 TypeError:conn.Price is not a constructor 因为混淆了 connection.model() 的处理方式。conn.model('Price',priceSchema) 确实在 conn 连接上注册了复制的 Price 模型,但并不会在conn 对象上创建一个名为 Price 的直接可访问属性。您需要获取 conn.model() 的返回值,该返回值就是模型构造的函数。实例化和操作特定连接的模型
一旦您正确地获取了特定连接上的模型构造函数(例如 PriceModelEn),就可以像使用普通 Mongoose 模型一样来实例化和操作。
// ... (承接上面的连接建立和 Schema 定义) ...// 异步函数用于数据操作 async function savePriceData() { try { // 使用 PriceModelEn 构造函数来创建文档实例 const newPrice = new PriceModelEn({fixed: { 1: 299, 3: 599 } }); // 保存文档到 db_en 数据库 const savingPrice = wait newPrice.save(); console.log('价格数据成功保存到db_en数据库:',savedPrice); //您也可以通过模型直接查询数据 const findPrice = wait PriceModelEn.findOne({ 'fixed.1': 299 }); console.log('从db_en数据库查询到的价格数据:',foundPrice); } catch (error) { console.error('保存查询或价格数据时发生错误:', error); } finally { // 在操作完成后,可以选择关闭连接 // dbEn.close(); // dbMain.close(); // 如果不再需要,也关闭主连接 }}// 调用函数执行数据savePriceData();// 示例:如果在 dbMain 上也有一个用户模型// const userSchema = new mongoose.Schema({ name: String });// const UserModelMain = dbMain.model('User', userSchema);// async function saveUserData() {// try {// const newUser = new UserModelMain({ name: 'Alice' });// wait newUser.save();// console.log('用户数据成功保存到db_main数据库:', newUser);// } catch (error) {// console.error('保存用户数据时发生错误:', error);// }// }// saveUserData();登录后复制事项注意事项与最佳实践连接管理: 确保您的应用程序在启动时建立所有需要的连接,并在应用程序关闭时缓慢地关闭它们。连接池: mongoose.createConnection() 默认会创建连接池。对于高并发应用,可以通过 connectionOptions 中的 poolSize 参数来调整连接池大小。
错误处理:务必监听连接的错误和断开事件,以便在连接出现问题时能够及时并处理,例如尝试重连。模型命名:由于不同的连接可以有同名的模型(因为它们绑定到不同的连接实例),但在代码中为它们使用不同的标志名(如 PriceModelEn 和 PriceModelMain)可以提高代码的警示性和避免中断。代码组织:将 Schema 定义、模型创建和数据操作逻辑进行的分离,例如将 Schema放在单独的文件中,模型创建逻辑放在数据库连接初始化部分。关闭连接:当应用程序不再需要某个连接时,应调用connection.close()来释放资源。总结
通过mongoose.createConnection(),Mongoose提供了强大的多数据库连接管理能力,允许您为不同的业务或数据类型隔离数据存储。关键在于理解connection.model()方法的正确用法:它返回的是构造的模型函数,必须将其赋值给一个变量才能用于实例化。遵循这些最佳实践,您可以有效地在 Mongoose 应用中管理和操作多个数据库。
以上就是 Mongoose 多数据库连接与模型管理深度指南的详细内容,更多请关注乐哥常识网其他相关文章!