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

IT技术 javascript node.js mongodb mongoose database
2021-01-12 04:14:01

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

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

    我试过在mongoose中使用createConnection()openSet(),但这不是解决方案。

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

我想知道是否可以使用带有 mongoose 的多个数据库或任何解决方法来解决此问题?因为我认为mongoose非常容易和快速。或任何其他module作为推荐?

6个回答

根据fine manualcreateConnection() 可以用来连接多个数据库。

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

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' }
}));

我很确定您可以在它们之间共享架构,但您必须检查以确保。

是的,我认为命名连接和共享模式是要走的路。根据 Robert 的示例,每个连接都需要一个唯一的模型。
2021-03-18 04:14:01
@AnoojKrishnanG 我认为这不可能,不。您需要分别针对每个数据库创建模型。但是,正如我在回答中已经说过的,您可以在连接之间共享模式,这可能会节省一些编码时间。
2021-03-29 04:14:01
假设我有自动生成的数据库(比如 n 个数据库)。不是一两个。有没有办法连接到这些而不为每个数据库创建单独的模型?
2021-03-30 04:14:01
您可以在不同的模型之间共享架构,因此也可以在 DB 之间共享。var newSchema = new mongoose.Schema({ ... }), var model2 = conn1.model('newModel', newSchema),var model2 = conn2.model('newModel', newSchema)
2021-03-31 04:14:01
useDb()可以在 3.8 中checkout以共享底层连接池:github.com/LearnBoost/mongoose/wiki/...
2021-04-10 04:14:01

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

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

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 是您的数据库名称。

正如@Wade 所说,据我所知,此解决方案仅在所有数据库都在同一台服务器上时才有效。目前尚不清楚这是否回答了 OP 的问题,而且 IMO 有点误导。
2021-03-21 04:14:01
谢谢 - 我能够在一个应用程序中使用 3 个不同的数据库: const mongoose = require('mongoose'); const Schema = mongoose.Schema; const mySchema = 新架构 ({}); const mydbvar = mongoose.connection.useDb('mydb') module.exports = mydbvar.model('myCollection', MySchema);
2021-03-24 04:14:01
这正是我从 MongoDB Atlas 迁移所需的test,也是为了避免有多个连接。但是,我也在.db最后 ( const v1 = mongoose.connection.useDb('test').db) ,因为旧的 db 不需要由mongoose管理。
2021-03-28 04:14:01
绝对是最好和最真实的例子。连接到默认数据库(就像您使用 SQL Server 之类的东西一样),然后利用 useDb 将 DML 定位到适当的数据库。(非常有助于将您的用户保存在一个数据库中并将您的数据保存在另一个数据库中。)当您最终将请求发送到同一台服务器时,无需开始建立多个连接。现在,如果您要连接到两个不同的服务器,那将是另一回事。
2021-03-31 04:14:01

您可以做的一件事是,您可能为每个项目都有子文件夹。因此,请在该子文件夹中安装 mongoose,并从每个子应用程序的自己的文件夹中安装 require() mongoose。不是来自项目根或全局。所以一个子项目,一个 mongoose 安装和一个 mongoose 实例。

-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

现在,您可以使用 mongoose 访问多个数据库。

你是我最好的朋友!非常感谢!这个对我有用!谢谢!
2021-03-12 04:14:01
每个应用程序有几个不同的连接实例(例如,用于用户数据库、会话数据库和应用程序数据)绝对没问题。这不是“巨大的负担”或会导致扩展问题,并且是一个常见的用例。
2021-03-16 04:14:01
这看起来对项目来说是一个巨大的负担。你不这么认为吗?
2021-03-19 04:14:01
xpepermint 你能展示一个 useDb 的例子吗——我目前遇到这个问题stackoverflow.com/questions/37583198/...
2021-03-31 04:14:01
这意味着每个项目都有自己的连接。您将无法管理 10 万个连接。我认为最好使用useDb使用相同连接池的命令。
2021-04-07 04:14:01

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

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

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

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

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

我将如何使用这种方法进行查询?
2021-03-17 04:14:01
这不是上面的答案,它更好。上面的答案不必要地安装了 Mongoose 的多个副本。
2021-03-24 04:14:01
await instance1.connection.collection('foo').insert({ foo: 'bar', }) await instance2.connection.collection('foo').insert({ foo: 'zoo', })
2021-03-24 04:14:01
这是写“高于答案”的另一种方式吗?
2021-03-27 04:14:01
事实上,在我的情况下更好地工作,因为我对每个连接都有完全不同的凭据,更不用说模型和数据库了。
2021-04-09 04:14:01

有点优化(至少对我而言)解决方案。将其写入文件 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;
    };
如何使用这种方式创建模态?
2021-03-13 04:14:01