2017-04-10 41 views
0

我正在開發一個項目,該項目將成爲多租戶Saas應用程序,並且難以根據用戶登錄信息實現登錄各種數據庫的方式。現在,我只想分割沙盒數據庫(用於演示目的,並將定期清除)和Alpha數據庫(用於當前客戶端測試和開發)之間的流量。我編寫了下面的中間件config.js,它在登錄時檢測用戶標識並使用mongoose.createConnection()分配數據庫對象。然後使用memory-cache將此鍵值對添加到商店。這裏是config.js代碼:如何根據登錄用戶將呼叫導向不同的實例MongoDB?

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 === '[email protected]'){ 
         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

你應該閱讀[這](http://stackoverflow.com/a/19475270/893780)。基本上,當你有不同的數據庫連接時,你需要分別註冊每個連接的模型。 'mongoose.connect()'不起作用,因爲你正在使用'mongoose.createConnection()'。 – robertklep

+0

感謝@robertklep,我確實讀過這篇文章,但由於兩個原因不清楚實施情況。 1.我的數據庫模式是相同的,顯然更多的是一個簡單的內聯模型。這似乎難以置信。當我重構整個應用程序時,您推薦使用相同模式(當前有5個模型)的方法是什麼? 2.一旦使用'mongoose.createConnection()'創建了連接,我應該立即連接到兩者嗎?在那種情況下,我以後如何路由到正確的連接?或者,我應該爲每個操作明確打開和關閉連接嗎?謝謝 – espressoAndCode

回答

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

+0

對不起,這似乎不是正確的解決方案。導致立即出現「連接失敗」錯誤並導致服務器崩潰。 – espressoAndCode

+0

好的。這可能不是完整的解決方案。你確定你的鍵值(內存緩存)存儲是直接保存對象嗎? – Tolsee

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(...); 
相關問題