首页 > web前端 > js教程 > 正文

Mongoose多数据库连接与模型管理深度解析

DDD
发布: 2025-07-30 14:42:22
原创
457人浏览过

Mongoose多数据库连接与模型管理深度解析

本教程深入探讨了Mongoose中如何高效管理多个数据库连接。我们将学习如何使用mongoose.createConnection建立独立的数据库连接,以及如何在这些特定连接上正确定义和实例化Mongoose模型,避免常见的TypeError: conn.Price is not a constructor错误,确保数据操作的准确性和隔离性。

Mongoose连接管理:默认与独立连接

在mongoose中,处理数据库连接主要有两种方式:使用mongoose.connect()建立默认连接,以及使用mongoose.createconnection()建立独立的连接实例。

  1. 默认连接 (mongoose.connect()): 当你调用mongoose.connect()时,Mongoose会建立一个全局的、默认的连接。此后,所有直接通过mongoose.model()定义和获取的模型都将绑定到这个默认连接上。这适用于大多数单数据库应用场景。

  2. 独立连接 (mongoose.createConnection()): 对于需要连接到多个数据库、或者需要对不同业务模块使用不同数据库连接的应用,mongoose.createConnection()是理想选择。它会返回一个独立的Connection实例,这个实例拥有自己的连接池和状态,与其他连接互不影响。这意味着你可以为每个数据库创建一个独立的连接对象,并在其上定义和操作模型,从而实现数据库操作的隔离。

    const mongoose = require('mongoose');
    
    // 统一的连接选项,可根据需要调整
    const connectionOptions = {
        useCreateIndex: true,
        useNewUrlParser: true,
        useUnifiedTopology: true,
        useFindAndModify: false
    };
    
    // 建立第一个数据库连接
    const dbEnConnection = mongoose.createConnection("mongodb://localhost/db_en", connectionOptions);
    
    // 建立第二个数据库连接
    const dbFrConnection = mongoose.createConnection("mongodb://localhost/db_fr", connectionOptions);
    
    // 可以在连接成功或失败时进行监听
    dbEnConnection.on('connected', () => console.log('Connected to db_en'));
    dbEnConnection.on('error', (err) => console.error('db_en connection error:', err));
    
    dbFrConnection.on('connected', () => console.log('Connected to db_fr'));
    dbFrConnection.on('error', (err) => console.error('db_fr connection error:', err));
    登录后复制

在特定连接上定义和注册模型

当使用mongoose.createConnection()创建了独立的连接实例后,模型的定义和注册方式与默认连接有所不同。你必须在特定的连接实例上调用model()方法来注册模型,而不是在全局的mongoose对象上。

  1. 定义Schema: 首先,像往常一样定义你的Mongoose Schema。Schema是模型的骨架,它定义了文档的结构、数据类型和验证规则。Schema的定义与连接无关,可以在任何地方进行。

    const priceSchema = new mongoose.Schema({
        fixed: {
            1: { type: Number, default: 199 },
            3: { type: Number, default: 499 },
            6: { type: Number, default: 729 },
            12: { type: Number, default: 999 }
        }
    });
    
    const productSchema = new mongoose.Schema({
        name: { type: String, required: true },
        price: { type: Number, required: true },
        currency: { type: String, default: 'USD' }
    });
    登录后复制
  2. 在特定连接上注册模型并获取构造函数: 关键在于使用连接实例的model()方法来注册Schema。这个方法接收两个参数:模型名称(字符串)和Schema对象。最重要的是,它会返回一个可以直接用于创建新文档的模型构造函数。

    // 在db_enConnection上注册Price模型
    // PriceModelEn 就是一个构造函数
    const PriceModelEn = dbEnConnection.model('Price', priceSchema);
    
    // 在db_frConnection上注册Product模型
    // ProductModelFr 也是一个构造函数
    const ProductModelFr = dbFrConnection.model('Product', productSchema);
    登录后复制

正确实例化和操作模型

一旦你通过connection.model()方法获取了模型构造函数,就可以使用它来创建新的文档实例,并执行保存、查询等操作。

// 使用db_enConnection上的Price模型
async function createPriceDocument() {
    // 正确的实例化方式:使用获取到的模型构造函数
    const priceDoc = new PriceModelEn();

    try {
        await priceDoc.save(); // 使用await确保异步操作完成
        console.log('价格文档已保存到 db_en:', priceDoc);
    } catch (error) {
        console.error('保存价格文档到 db_en 失败:', error);
    }
}

// 使用db_frConnection上的Product模型
async function createProductDocument() {
    // 正确的实例化方式:使用获取到的模型构造函数
    const productDoc = new ProductModelFr({ name: 'French Baguette', price: 2.50 });

    try {
        await productDoc.save();
        console.log('产品文档已保存到 db_fr:', productDoc);
    } catch (error) {
        console.error('保存产品文档到 db_fr 失败:', error);
    }
}
登录后复制

常见错误与最佳实践

错误解析:TypeError: conn.Price is not a constructor

这个错误通常发生在尝试像访问对象属性一样访问模型时,例如new conn.Price()。Mongoose的Connection对象并没有一个名为Price的直接属性来作为模型构造函数。当你调用conn.model('Price', priceSchema)时,它是在该连接实例上注册了一个名为'Price'的模型,并且返回了这个模型的构造函数。因此,你必须捕获这个返回值,并使用它来实例化文档。

区分 mongoose.model() 和 connectionInstance.model()

FashionLabs
FashionLabs

AI服装模特、商品图,可商用,低价提升销量神器

FashionLabs 38
查看详情 FashionLabs
  • mongoose.model('ModelName', Schema):用于在默认连接上定义和获取模型。
  • connectionInstance.model('ModelName', Schema):用于在特定独立连接上定义和获取模型。

务必根据你使用的连接类型来选择正确的方法。

最佳实践:

  • 明确的变量命名: 将connection.model()返回的模型构造函数赋值给一个清晰的变量名(例如PriceModelEn),这样可以提高代码的可读性,并避免混淆。
  • 异步操作处理: Mongoose的保存和查询操作都是异步的。始终使用async/await或Promise的.then().catch()来处理这些操作,确保代码的正确执行顺序和错误捕获。
  • 连接管理: 在应用程序启动时建立所有必要的连接,并在应用程序关闭时优雅地关闭它们,以释放资源。

完整示例代码

下面是一个整合了上述概念的完整示例,展示了如何使用两个独立的Mongoose连接来操作不同数据库中的模型。

const mongoose = require('mongoose');

// 统一的连接选项
const connectionOptions = {
    useCreateIndex: true,
    useNewUrlParser: true,
    useUnifiedTopology: true,
    useFindAndModify: false
};

// --- 第一数据库连接:db_en ---
const dbEnConnection = mongoose.createConnection("mongodb://localhost/db_en", connectionOptions);

dbEnConnection.on('connected', () => console.log('Successfully connected to db_en'));
dbEnConnection.on('error', (err) => console.error('db_en connection error:', err));
dbEnConnection.on('disconnected', () => console.log('Disconnected from db_en'));

// 定义价格Schema
const priceSchema = new mongoose.Schema({
    fixed: {
        1: { type: Number, default: 199 },
        3: { type: Number, default: 499 },
        6: { type: Number, default: 729 },
        12: { type: Number, default: 999 }
    }
});

// 在db_enConnection上注册Price模型并获取构造函数
const PriceModelEn = dbEnConnection.model('Price', priceSchema);

// --- 第二数据库连接:db_fr ---
const dbFrConnection = mongoose.createConnection("mongodb://localhost/db_fr", connectionOptions);

dbFrConnection.on('connected', () => console.log('Successfully connected to db_fr'));
dbFrConnection.on('error', (err) => console.error('db_fr connection error:', err));
dbFrConnection.on('disconnected', () => console.log('Disconnected from db_fr'));

// 定义产品Schema
const productSchema = new mongoose.Schema({
    name: { type: String, required: true },
    price: { type: Number, required: true },
    currency: { type: String, default: 'EUR' }
});

// 在db_frConnection上注册Product模型并获取构造函数
const ProductModelFr = dbFrConnection.model('Product', productSchema);

// --- 示例操作函数 ---

async function createPriceDocument() {
    console.log('\n--- 尝试在 db_en 中创建价格文档 ---');
    const priceDoc = new PriceModelEn(); // 使用正确的模型构造函数
    try {
        await priceDoc.save();
        console.log('价格文档已成功保存到 db_en:', priceDoc);
    } catch (error) {
        console.error('保存价格文档到 db_en 失败:', error.message);
    }
}

async function createProductDocument() {
    console.log('\n--- 尝试在 db_fr 中创建产品文档 ---');
    const productDoc = new ProductModelFr({ name: 'Laptop', price: 1200.00 });
    try {
        await productDoc.save();
        console.log('产品文档已成功保存到 db_fr:', productDoc);
    } catch (error) {
        console.error('保存产品文档到 db_fr 失败:', error.message);
    }
}

async function runAllExamples() {
    await createPriceDocument();
    await createProductDocument();

    // 示例查询
    console.log('\n--- 尝试从 db_en 查询价格文档 ---');
    try {
        const prices = await PriceModelEn.find({});
        console.log('db_en 中的价格文档:', prices);
    } catch (error) {
        console.error('从 db_en 查询失败:', error.message);
    }

    console.log('\n--- 尝试从 db_fr 查询产品文档 ---');
    try {
        const products = await ProductModelFr.find({});
        console.log('db_fr 中的产品文档:', products);
    } catch (error) {
        console.error('从 db_fr 查询失败:', error.message);
    }

    // 关闭所有连接
    console.log('\n--- 关闭数据库连接 ---');
    await dbEnConnection.close();
    await dbFrConnection.close();
    console.log('所有数据库连接已关闭。');
}

// 运行所有示例
runAllExamples().catch(console.error);
登录后复制

总结

通过本教程,我们深入理解了Mongoose中多数据库连接的管理策略。核心要点在于:当使用mongoose.createConnection()建立独立连接时,必须在该连接实例上调用connection.model()来注册和获取模型构造函数。避免直接将连接对象作为模型的容器(如conn.Price),因为这会导致TypeError。正确地使用connection.model()的返回值,将使你在Mongoose多数据库环境中高效、准确地进行数据操作。

以上就是Mongoose多数据库连接与模型管理深度解析的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号