单个 node.js 项目中的 Mongoose 和多个数据库

我正在做一个包含子项目的 Node.js 项目。一个子项目将有一个 Mongodb 数据库,Mongoose 将用于包装和查询 db。但问题是

  • Mongoose 不允许在单个实例中使用多个数据库,因为模型是建立在一个连接上的。
  • 要使用多个 monose 实例,Node.js 不允许多个模块实例,因为它在 require()中有缓存系统。我知道在 Node.js 中禁用模块缓存,但我认为这不是一个好的解决方案,因为它只是猫鼬的需要。

    我试过在猫鼬身上使用 createConnection()openSet(),但这不是解决办法。

    我尝试深度复制猫鼬实例(http://blog.imaginea.com/deep-copy-in-javascript/)以将新的猫鼬实例传递给子项目,但它抛出了 RangeError: Maximum call stack size exceeded

我想知道是否有任何方式使用多数据库与猫鼬或任何解决方案这个问题?因为我觉得猫鼬很容易又快。或任何其他模块作为建议?

150692 次浏览

您可以做的一件事情是,您可以为每个项目设置子文件夹。因此,在该子文件夹中安装猫鼬,并要求在每个子应用程序的自己的文件夹中安装()猫鼬。不是从项目根目录或全局目录。所以一个子项目,一个猫鼬装置和一个猫鼬实例。

-app_root/
--foo_app/
---db_access.js
---foo_db_connect.js
---node_modules/
----mongoose/
--bar_app/
---db_access.js
---bar_db_connect.js
---node_modules/
----mongoose/

在 foo _ db _ connect. js 中

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/foo_db');
module.exports = exports = mongoose;

在 bar _ db _ connect. js 中

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/bar_db');
module.exports = exports = mongoose;

在 db _ access. js 文件中

var mongoose = require("./foo_db_connect.js"); // bar_db_connect.js for bar app

用猫鼬可以访问多个数据库。

根据 精美的手册createConnection() 可以用于连接多个数据库。

但是,您需要为每个连接/数据库创建单独的模型:

var conn      = mongoose.createConnection('mongodb://localhost/testA');
var conn2     = mongoose.createConnection('mongodb://localhost/testB');


// stored in 'testA' database
var ModelA    = conn.model('Model', new mongoose.Schema({
title : { type : String, default : 'model in testA database' }
}));


// stored in 'testB' database
var ModelB    = conn2.model('Model', new mongoose.Schema({
title : { type : String, default : 'model in testB database' }
}));

我非常确定您可以在它们之间共享模式,但是您必须进行检查以确保。

作为替代方法,Mongoose 确实在默认实例上为新实例导出构造函数。所以这样的事情是有可能的。

var Mongoose = require('mongoose').Mongoose;


var instance1 = new Mongoose();
instance1.connect('foo');


var instance2 = new Mongoose();
instance2.connect('bar');

这在处理单独的数据源时非常有用,当您希望为每个用户或请求提供单独的数据库上下文时也是如此。您需要小心,因为在执行此操作时可能会创建大量连接。确保在不需要实例时调用 disconnect () ,并限制每个实例创建的池大小。

很晚了,不过这个可能会有帮助。当前的答案假定您对连接和模型使用相同的文件。

在现实生活中,很有可能将模型分割成不同的文件。您可以在主文件中使用类似的内容:

mongoose.connect('mongodb://localhost/default');


const db = mongoose.connection;


db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', () => {
console.log('connected');
});

文件里是这么描述的。然后在模型文件中,执行以下操作:

import mongoose, { Schema } from 'mongoose';


const userInfoSchema = new Schema({
createdAt: {
type: Date,
required: true,
default: new Date(),
},
// ...other fields
});


const myDB = mongoose.connection.useDb('myDB');


const UserInfo = myDB.model('userInfo', userInfoSchema);


export default UserInfo;

其中 myDB 是您的数据库名称。

一个有点优化(至少对我来说)的解决方案。把它写到 db.js 文件中,并要求它到任何需要的地方,然后用函数调用调用它,这样就可以了。

   const MongoClient = require('mongodb').MongoClient;
async function getConnections(url,db){
return new Promise((resolve,reject)=>{
MongoClient.connect(url, { useUnifiedTopology: true },function(err, client) {
if(err) { console.error(err)
resolve(false);
}
else{
resolve(client.db(db));
}
})
});
}


module.exports = async function(){
let dbs      = [];
dbs['db1']     = await getConnections('mongodb://localhost:27017/','db1');
dbs['db2']     = await getConnections('mongodb://localhost:27017/','db2');
return dbs;
};

单个 node.js 项目中的 Mongoose 和多个数据库

使用 UseDb来解决这个问题

例子

//product databse
const myDB = mongoose.connection.useDb('product');
module.exports = myDB.model("Snack", snackSchema);
//user databse
const myDB = mongoose.connection.useDb('user');
module.exports = myDB.model("User", userSchema);

我一直在使用这种方法,它对我来说很有效,直到现在。

const mongoose = require('mongoose');


function makeNewConnection(uri) {
const db = mongoose.createConnection(uri, {
useNewUrlParser: true,
useUnifiedTopology: true
});


db.on('error', function (error) {
console.log(`MongoDB :: connection ${this.name} ${JSON.stringify(error)}`);
db.close().catch(() => console.log(`MongoDB :: failed to close connection ${this.name}`));
});


db.on('connected', function () {
mongoose.set('debug', function (col, method, query, doc) {
console.log(`MongoDB :: ${this.conn.name} ${col}.${method}(${JSON.stringify(query)},${JSON.stringify(doc)})`);
});
console.log(`MongoDB :: connected ${this.name}`);
});


db.on('disconnected', function () {
console.log(`MongoDB :: disconnected ${this.name}`);
});


return db;
}


// Use


const db1 = makeNewConnection(MONGO_URI_DB1);
const db2 = makeNewConnection(MONGO_URI_DB2);


module.exports = {
db1,
db2
}