我使用node-mongodb-native驱动与MongoDB写一个网站。

我有一些关于如何管理连接的问题:

Is it enough using only one MongoDB connection for all requests? Are there any performance issues? If not, can I setup a global connection to use in the whole application? If not, is it good if I open a new connection when request arrives, and close it when handled the request? Is it expensive to open and close a connection? Should I use a global connection pool? I hear the driver has a native connection pool. Is it a good choice? If I use a connection pool, how many connections should be used? Are there other things I should notice?


当前回答

如果使用express,还有另一种更直接的方法,即利用express的内置功能在应用程序中的路由和模块之间共享数据。有一个名为app.locals的对象。我们可以给它附加属性,并从我们的路由内部访问它。要使用它,在app.js文件中实例化你的mongo连接。

var app = express();

MongoClient.connect('mongodb://localhost:27017/')
.then(client =>{
  const db = client.db('your-db');
  const collection = db.collection('your-collection');
  app.locals.collection = collection;
});
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              // view engine setup
app.set('views', path.join(__dirname, 'views'));

这个数据库连接,或者你希望在应用程序的模块周围共享的任何其他数据,现在都可以通过req.app.locals在你的路由中访问,而不需要创建和要求额外的模块。

app.get('/', (req, res) => {
  const collection = req.app.locals.collection;
  collection.find({}).toArray()
  .then(response => res.status(200).json(response))
  .catch(error => console.error(error));
});

此方法确保在应用程序运行期间有一个数据库连接是打开的,除非您选择在任何时候关闭它。它可以通过req.app.locals轻松访问。您的集合,不需要创建任何额外的模块。

其他回答

如果使用express,还有另一种更直接的方法,即利用express的内置功能在应用程序中的路由和模块之间共享数据。有一个名为app.locals的对象。我们可以给它附加属性,并从我们的路由内部访问它。要使用它,在app.js文件中实例化你的mongo连接。

var app = express();

MongoClient.connect('mongodb://localhost:27017/')
.then(client =>{
  const db = client.db('your-db');
  const collection = db.collection('your-collection');
  app.locals.collection = collection;
});
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              // view engine setup
app.set('views', path.join(__dirname, 'views'));

这个数据库连接,或者你希望在应用程序的模块周围共享的任何其他数据,现在都可以通过req.app.locals在你的路由中访问,而不需要创建和要求额外的模块。

app.get('/', (req, res) => {
  const collection = req.app.locals.collection;
  collection.find({}).toArray()
  .then(response => res.status(200).json(response))
  .catch(error => console.error(error));
});

此方法确保在应用程序运行期间有一个数据库连接是打开的,除非您选择在任何时候关闭它。它可以通过req.app.locals轻松访问。您的集合,不需要创建任何额外的模块。

实现连接池的最佳方法是创建一个全局数组变量,其中包含由MongoClient返回的db名称和连接对象,然后在需要联系数据库时重用该连接。

In your Server.js define var global.dbconnections = []; Create a Service naming connectionService.js. It will have 2 methods getConnection and createConnection. So when user will call getConnection(), it will find detail in global connection variable and return connection details if already exists else it will call createConnection() and return connection Details. Call this service using <db_name> and it will return connection object if it already have else it will create new connection and return it to you.

希望能有所帮助。

下面是connectionService.js的代码:

var mongo = require('mongoskin');
var mongodb = require('mongodb');
var Q = require('q');
var service = {};
service.getConnection = getConnection ;
module.exports = service;

function getConnection(appDB){
    var deferred = Q.defer();
    var connectionDetails=global.dbconnections.find(item=>item.appDB==appDB)

    if(connectionDetails){deferred.resolve(connectionDetails.connection);
    }else{createConnection(appDB).then(function(connectionDetails){
            deferred.resolve(connectionDetails);})
    }
    return deferred.promise;
}

function createConnection(appDB){
    var deferred = Q.defer();
    mongodb.MongoClient.connect(connectionServer + appDB, (err,database)=> 
    {
        if(err) deferred.reject(err.name + ': ' + err.message);
        global.dbconnections.push({appDB: appDB,  connection: database});
        deferred.resolve(database);
    })
     return deferred.promise;
} 

如果你有Express.js,你可以使用express- MongoDB -db在请求之间缓存和共享MongoDB连接,而不需要一个池(因为接受的答案说这是共享连接的正确方式)。

如果没有,你可以查看它的源代码并在另一个框架中使用它。

node-mongodb-native的主提交者说:

打开MongoClient。连接一次,当你的应用程序启动和重用 db对象。每个.connect并不是一个单独的连接池 创建一个新的连接池。

因此,为了直接回答您的问题,重用MongoClient.connect()生成的db对象。这为您提供了池化,与在每个db操作上打开/关闭连接相比,将提供显著的速度提高。

npm i express mongoose

mongodb.js

const express = require('express');
const mongoose =require('mongoose')
const app = express();

mongoose.set('strictQuery', true);
mongoose.connect('mongodb://localhost:27017/db_name', {
    useNewUrlParser: true, 
    useUnifiedTopology: true
})
.then(() => console.log('MongoDB Connected...'))
.catch((err) => console.log(err))

app.listen(3000,()=>{ console.log("Started on port 3000 !!!") })
node mongodb.js