我正在开发一个多租户Saas应用程序的项目,并且很难实现根据用户登录信息登录各种数据库的方法。现在,我只想在Sandbox数据库(用于演示目的,将定期擦除)和Alpha数据库(用于当前客户端测试和开发)之间分配流量。我编写了下面的中间件config.js
,它在登录时检测用户ID并使用mongoose.createConnection()
分配数据库对象。然后使用memory-cache
将此键值对添加到商店。这是config.js
代码:
var mcache = require('memory-cache'),
Promise = require("bluebird"),
mongoose = require('mongoose');
Promise.promisifyAll(require("mongoose"));
(function () {
'use strict';
var dbSand = mongoose.createConnection(process.env.DB_SAND);
var dbAlpha = mongoose.createConnection(process.env.DB_ALPHA);
function dbPathConfigMiddlewareWrapper (){
return function setDbPath(req, res, next){
if ( req ){
if (!mcache.get(req.session.id) && req.body.email){
var login = req.body.email;
if (login === 'demo@mysite.com'){
mcache.put(req.session.id, dbSand);
} else {
mcache.put(req.session.id, dbAlpha);
}
}
req.dbPath = mcache.get(req.session.id);
next();
}
};
}
module.exports = dbPathConfigMiddlewareWrapper;
}());
到目前为止一切顺利。但是我在路由中调用正确的数据库是不成功的。当我刚刚使用单个数据库时,我可以轻松地使用它:
var connStr = process.env.DBPATH;
if(mongoose.connection.readyState === 0){
mongoose.connect(connStr, function(err) {
if (err) throw err;
console.log('Successfully connected to MongoDB');
});
}
现在,我试图这样做无济于事:
var connStr = req.dbPath; //where req.dbPath is assigned in the config middleware above.
if(connStr.connection.readyState === 0){
mongoose.connect(req.dbPath, function(err) {
if (err) throw err;
console.log('Successfully connected to MongoDB');
});
}
非常感谢任何指导。这似乎应该更加直截了当,文档提到了它,但没有详细说明。
答案 0 :(得分:0)
我认为,问题在于您将数据库对象保存到键值存储中。 mcache.put(req.session.id, dbSand);
。这导致了if(connStr.connection.readyState === 0)
中的错误。
您可以对对象进行字符串化。 mcache.put(req.session.id, JSON.stringify(dbSand));
。并获取对象的字符串并将其解析为JSON,如var connStr = JSON.parse(req.dbPath);
。
答案 1 :(得分:0)
如果您手动创建连接,则无法致电mongoose.connect()
。
相反,你必须为每个连接注册你的模型,这有点像PITA,但据我所知,没有办法解决这个问题。可能需要对代码进行一些重组。
这里有一些关于如何设置类似内容的未经测试的代码。
您的中间件文件:
// Create connections
const registerModels = require('./register-models');
let dbSand = mongoose.createConnection(process.env.DB_SAND);
let dbAlpha = mongoose.createConnection(process.env.DB_ALPHA);
// Register your models for each connection.
registerModels(dbSand);
registerModels(dbAlpha);
function dbPathConfigMiddlewareWrapper() { ... }
寄存器models.js:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
let UserSchema = new mongoose.Schema(...);
module.exports = function(conn) {
conn.model('User', UserSchema);
};
这确实意味着您无法在路线中使用User.find(...)
,因为只有在您使用单一连接时才会使用{默认的连接mongoose.connect()
,你没有使用的。)
相反,你应该在你的路线中使用这样的东西:
req.dbPath.model('User').find(...);