我使用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轻松访问。您的集合,不需要创建任何额外的模块。

其他回答

如果有人想在2021年用Typescript工作,这是我正在使用的:

import { MongoClient, Collection } from "mongodb";

const FILE_DB_HOST = process.env.FILE_DB_HOST as string;
const FILE_DB_DATABASE = process.env.FILE_DB_DATABASE as string;
const FILES_COLLECTION = process.env.FILES_COLLECTION as string;

if (!FILE_DB_HOST || !FILE_DB_DATABASE || !FILES_COLLECTION) {
  throw "Missing FILE_DB_HOST, FILE_DB_DATABASE, or FILES_COLLECTION environment variables.";
}

const client = new MongoClient(FILE_DB_HOST, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});

class Mongoose {
  static FilesCollection: Collection;

  static async init() {
    const connection = await client.connect();
    const FileDB = connection.db(FILE_DB_DATABASE);
    Mongoose.FilesCollection = FileDB.collection(FILES_COLLECTION);
  }
}


Mongoose.init();

export default Mongoose;

我相信如果请求发生得太快(在蒙古.init()有时间完成之前),将会抛出一个错误,因为Mongoose。FilesCollection将未定义。

import { Request, Response, NextFunction } from "express";
import Mongoose from "../../mongoose";

export default async function GetFile(req: Request, res: Response, next: NextFunction) {
  const files = Mongoose.FilesCollection;
  const file = await files.findOne({ fileName: "hello" });
  res.send(file);
}

例如,如果您调用文件。findOne({…})和猫鼬。FilesCollection未定义,那么您将得到一个错误。

我已经在我的项目中实现了下面的代码,在我的代码中实现连接池,这样它将在我的项目中创建一个最小的连接,并重用可用的连接

/* Mongo.js*/

var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/yourdatabasename"; 
var assert = require('assert');

var connection=[];
// Create the database connection
establishConnection = function(callback){

                MongoClient.connect(url, { poolSize: 10 },function(err, db) {
                    assert.equal(null, err);

                        connection = db
                        if(typeof callback === 'function' && callback())
                            callback(connection)

                    }

                )



}

function getconnection(){
    return connection
}

module.exports = {

    establishConnection:establishConnection,
    getconnection:getconnection
}

/*app.js*/
// establish one connection with all other routes will use.
var db = require('./routes/mongo')

db.establishConnection();

//you can also call with callback if you wanna create any collection at starting
/*
db.establishConnection(function(conn){
  conn.createCollection("collectionName", function(err, res) {
    if (err) throw err;
    console.log("Collection created!");
  });
};
*/

// anyother route.js

var db = require('./mongo')

router.get('/', function(req, res, next) {
    var connection = db.getconnection()
    res.send("Hello");

});

您应该将连接创建为服务,然后在需要时重用它。

// db.service.js
import { MongoClient } from "mongodb";
import database from "../config/database";

const dbService = {
  db: undefined,
  connect: callback => {
    MongoClient.connect(database.uri, function(err, data) {
      if (err) {
        MongoClient.close();
        callback(err);
      }
      dbService.db = data;
      console.log("Connected to database");
      callback(null);
    });
  }
};

export default dbService;

我的App.js样本

// App Start
dbService.connect(err => {
  if (err) {
    console.log("Error: ", err);
    process.exit(1);
  }

  server.listen(config.port, () => {
    console.log(`Api runnning at ${config.port}`);
  });
});

想用就用吧

import dbService from "db.service.js"
const db = dbService.db

我一直在我的应用程序中使用redis连接的通用池-我强烈推荐它。它是通用的,我肯定知道它适用于mysql,所以我不认为你会有任何问题与它和mongo

https://github.com/coopernurse/node-pool

实现连接池的最佳方法是创建一个全局数组变量,其中包含由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;
}