2013-08-04 55 views
12

我在express.js應用程序中使用了mongodb-native-driver。我在數據庫中有大約6個集合,所以我創建了6個js文件,每個文件都有一個作爲javascript對象的集合(例如function collection(){}),而原型函數處理這些集合的所有操作。我認爲這將是一個很好的建築。在express.js中連接到Mongodb-Native-Driver

但是我遇到的問題是如何連接數據庫?我應該在每個文件中創建一個連接並使用它們嗎?我認爲這將是一個矯枉過正的問題,因爲mongodb-native-driver中的連接創建了一個連接池,並且其中有幾個連接是不合理的。

那麼如何創建單個連接池並將其用於所有collections.js文件?我想要像在貓鼬中實現它的連接。讓我知道,如果我的任何應用程序的體系結構思維過程是錯誤的。

使用Mongoose可以解決這些問題,但我已經在幾個地方看過,它比native-driver慢,而且我更喜歡無模式模型。

編輯:我用模型創建了一個模塊。每個集合都在一個文件中,並將數據庫作爲參數。現在在index.js文件中,我調用了數據庫連接,並在從連接獲取數據庫後保留了一個變量db。 (我使用了自動重新連接功能來確保連接沒有丟失)。在同一index.js文件我出口每個集合的這樣

exports.model1 = require('./model1').(db) 
exprorts.model2 = require('./model2').(db) 

這確保了數據庫的一部分,在短短一個模塊處理和應用程序只需調用每個model.js文件導出像save()功能,fincdbyid()等(whatever you do in the function is upto you to implement)。

回答

17

如何連接數據庫?

爲了使用你需要做類似下面的MongoDB的原生驅動程序連接:

var util = require('util'); 
var mongodb = require('mongodb'); 
var client = mongodb.MongoClient; 

var auth = { 
    user: 'username', 
    pass: 'password', 
    host: 'hostname', 
    port: 1337, 
    name: 'databaseName' 
}; 

var uri = util.format('mongodb://%s:%[email protected]%s:%d/%s', 
    auth.user, auth.pass, auth.host, auth.port, auth.name); 

/** Connect to the Mongo database at the URI using the client */ 
client.connect(uri, { auto_reconnect: true }, function (err, database) { 
    if (err) throw err; 
    else if (!database) console.log('Unknown error connecting to database'); 
    else { 

     console.log('Connected to MongoDB database server at:'); 
     console.log('\n\t%s\n', uri); 

     // Create or access collections, etc here using the database object 
    } 
}); 

一個基本的連接設置這樣的。這就是我可以給你的只是你想要的基本描述。發佈一些你到目前爲止獲得更多具體幫助的代碼。

我應該在每個文件中創建一個連接並使用它們嗎?

那麼,如何創建一個連接池,並在所有的collections.js文件使用它?

你可以用上面的代碼創建一個單獨的文件,我們把它叫做dbmanager.js連接到數據庫。導出功能如createUser,deleteUser等這對數據庫進行操作,那麼像這樣導出功能:

module.exports = { 
    createUser: function() { ; }, 
    deleteUser: function() { ; } 
}; 

然後你可以從require像這樣另一個文件:

var dbman = require('./dbmanager'); 

dbman.createUser(userData); // using connection established in `dbmanager.js` 

編輯:因爲我們正在處理JavaScript和一單線程,本地驅動程序確實自動爲您處理連接池。你可以在下面的StackOverflow鏈接中查找,以獲得更多的確認。 OP也在這個問題中陳述了這一點。這意味着client.connect應該只被您的服務器的一個實例調用一次。在從client.connect的調用中成功檢索到database對象之後,該database對象應該在整個應用程序的整個實例中重用。這很容易通過使用Node.JS提供的模塊模式來完成。

我的建議是創建一個模塊或一組模塊作爲與數據庫交互的單一聯繫點。在我的應用程序中,我通常有一個模塊,它取決於本地驅動程序,調用require('mongodb')。我的應用程序中的所有其他模塊不會直接訪問數據庫,而是所有操作都必須由此數據庫模塊進行協調。

這將所有處理本地驅動程序的代碼封裝到一個模塊或一組模塊中。 OP似乎認爲我發佈的簡單代碼示例存在一個問題,在我的示例中描述了一個「單個大閉包」的問題。這是非常基本的東西,所以我在這裏添加了關於基本架構的說明,但我仍然不覺得需要更改任何代碼。

OP也似乎認爲可能在這裏創建多個連接。這是不可能的這種設置。如果你創建了一個像我上面建議的模塊,那麼第一次調用require('./dbmanager')就會執行文件dbmanager.js中的代碼返回module.exports對象。導出對象被緩存,並在每次後續調用require('./dbmanager')時返回,但dbmanager.js中的代碼僅執行第一個require

如果您不想創建一個像這樣的模塊,那麼另一種選擇是僅導出傳遞給client.connect的回調的database,並將其直接用於整個應用的不同位置。不過,我建議反對這一點,不管OP的擔憂。

類似,可能重複#1的問題,其中包括:

+0

我已經考慮過你給出的解決方案,但沒有繼續,因爲正如我上面所說的,我有大約6個集合以及不得不將所有操作寫在一個大閉包內的想法。其次,在您的方法中,有可能會建立多個連接,因爲它不會檢查是否已連接。 –

+0

無論您需要多少次(./ dbmanager),它都不會多次調用client.connect。如果運行多個服務器實例,多個連接的唯一「機會」就是如此。 Node.JS將只在第一次需要時才執行代碼,每次後續調用只返回'exports'。 –

+0

-1缺乏解釋。與你的評論相反,你從來沒有提到任何關於你的問題中的單一封閉。我特別回答你的每個問題:他們關於你是否應該在多個不同的文件中創建連接。我支持我的回答:沒有必要。 –

2

作爲公認的答案說 - 你應該爲所有傳入的請求只有一個連接並重用它,但答案是缺少的解決方案,這將創建並緩存連接。我寫了快遞中間件來實現這一點 - express-mongo-db。乍一看,這個任務是微不足道的,而大多數人使用這種代碼:

var db; 
function createConnection(req, res, next) { 
    if (db) { req.db = db; next(); } 
    client.connect(uri, { auto_reconnect: true }, function (err, database) { 
     req.db = db = databse; 
     next(); 
    }); 
} 

app.use(createConnection); 

但這個代碼導致你的連接泄漏,當多個請求到達的同時,並db是不確定的。 express-mongo-db解決這個問題的方法是,只需要模塊(不是第一個請求到達時),只需要一次撥入connect即可保留傳入客戶端。

希望你覺得它有用。

0

我只是想我會在我自己的MongoDB連接的方法添加感興趣的其他人或有問題用不同的方法

此方法假定你不需要身份驗證(我用這個在localhost)

驗證仍然容易實現

var MongoClient = require('mongodb').MongoClient; 
var Server  = require('mongodb').Server; 

var client = new MongoClient(new Server('localhost',27017,{ 
           socketOptions: {connectTimeoutMS: 500}, 
           poolSize:5, 
           auto_reconnect:true 
          }, { 
           numberOfRetries:3, 
           retryMilliseconds: 500 
          })); 

client.open(function(err, client) { 
    if(err) { 
     console.log("Connection Failed Via Client Object."); 
    } else { 
     var db = client.db("theDbName"); 
     if(db) { 
      console.log("Connected Via Client Object . . ."); 
      db.logout(function(err,result) { 
       if(!err) { 
        console.log("Logged out successfully"); 
       } 
       client.close(); 
       console.log("Connection closed"); 
      }); 
     } 
    } 
}); 

幸得布拉德Davley肚裏了這種方法在他的book(頁231-232)