Comment gérer les connexions MongoDB dans un nœud.application web js?

J'utilise le pilotenode-mongodb-native avec MongoDB pour écrire un site web.

J'ai quelques questions sur la façon de gérer les connexions:

  1. Est-il suffisant d'utiliser une seule connexion MongoDB pour toutes les demandes? Existe-il des problèmes de performance? Si non, puis-je configurer une connexion globale à utiliser dans l'ensemble de l'application?

  2. Si ce n'est pas le cas, est-il bon que j'ouvre une nouvelle connexion lorsque la demande arrive,et la ferme lorsque la demande est traitée? Est-il cher pour ouvrir et fermer une connexion?

  3. Dois-je utiliser un pool de connexions global? J'entends que le pilote a un pool de connexion natif. Est-ce un bon choix?

  4. Si j'utilise un pool de connexions, combien de connexions doivent être utilisées?

  5. Y a-t-il d'autres choses que je devrais remarquer?

216
demandé sur Peter Mortensen 2012-05-18 20:42:34

10 réponses

Le valideur principal de node-mongodb-native dit :

Vous ouvrez faire MongoClient.connectez-vous une fois lorsque votre application démarre et réutilise la db objet. Ce n'est pas un pool de connexion singleton chacun .connecter crée un nouveau pool de connexions.

Donc, pour répondre directement à votre question, réutilisez l'objet db résultant de MongoClient.connecter(). Cela vous donne la mise en commun, et fournira une augmentation notable de la vitesse par rapport à l'ouverture / fermeture des connexions sur chaque db action.

381
répondu Max 2013-01-22 17:41:07

Ouvrir une nouvelle connexion lorsque le Nœud.l'application js démarre et réutilise l'objet de connexion db existant:

/server.js

import express from 'express';
import Promise from 'bluebird';
import logger from 'winston';
import { MongoClient } from 'mongodb';
import config from './config';
import usersRestApi from './api/users';

const app = express();

app.use('/api/users', usersRestApi);

app.get('/', (req, res) => {
  res.send('Hello World');
});

// Create a MongoDB connection pool and start the application
// after the database connection is ready
MongoClient.connect(config.database.url, { promiseLibrary: Promise }, (err, db) => {
  if (err) {
    logger.warn(`Failed to connect to the database. ${err.stack}`);
  }
  app.locals.db = db;
  app.listen(config.port, () => {
    logger.info(`Node.js app is listening at http://localhost:${config.port}`);
  });
});

/api/users.js

import { Router } from 'express';
import { ObjectID } from 'mongodb';

const router = new Router();

router.get('/:id', async (req, res, next) => {
  try {
    const db = req.app.locals.db;
    const id = new ObjectID(req.params.id);
    const user = await db.collection('user').findOne({ _id: id }, {
      email: 1,
      firstName: 1,
      lastName: 1
    });

    if (user) {
      user.id = req.params.id;
      res.send(user);
    } else {
      res.sendStatus(404);
    }
  } catch (err) {
    next(err);
  }
});

export default router;

Source: Comment ouvrir des connexions de base de données dans un nœud.js / Express App

30
répondu Konstantin Tarkus 2017-01-15 18:26:58

Voici un code qui va gérer vos connexions MongoDB.

var MongoClient = require('mongodb').MongoClient;
var url = require("../config.json")["MongoDBURL"]

var option = {
  db:{
    numberOfRetries : 5
  },
  server: {
    auto_reconnect: true,
    poolSize : 40,
    socketOptions: {
        connectTimeoutMS: 500
    }
  },
  replSet: {},
  mongos: {}
};

function MongoPool(){}

var p_db;

function initPool(cb){
  MongoClient.connect(url, option, function(err, db) {
    if (err) throw err;

    p_db = db;
    if(cb && typeof(cb) == 'function')
        cb(p_db);
  });
  return MongoPool;
}

MongoPool.initPool = initPool;

function getInstance(cb){
  if(!p_db){
    initPool(cb)
  }
  else{
    if(cb && typeof(cb) == 'function')
      cb(p_db);
  }
}
MongoPool.getInstance = getInstance;

module.exports = MongoPool;

Lorsque vous démarrez le serveur, appelez - initPool

require("mongo-pool").initPool();

Ensuite, dans tout autre module, vous pouvez faire ce qui suit:

var MongoPool = require("mongo-pool");
MongoPool.getInstance(function (db){
    // Query your MongoDB database.
});

Ceci est basé sur la documentation MongoDB . Prendre un coup d'oeil.

14
répondu Yaki Klein 2017-01-15 18:28:49

Si vous avez Express.js, vous pouvez utiliser express-mongo-db pour mettre en cache et partager la connexion MongoDB entre les requêtes sans pool (puisque la réponse acceptée indique que c'est la bonne façon de partager la connexion).

Sinon - vous pouvez regarder son code source et l'utiliser dans un autre framework.

11
répondu floatdrop 2017-01-15 18:25:01

Gérer les pools de connexion mongo dans un seul module autonome. Cette approche offre deux avantages. Tout d'abord, il maintient votre code modulaire et plus facile à tester. Deuxièmement, vous n'êtes pas obligé de mélanger votre connexion à la base de données dans votre objet de requête qui n'est pas l'endroit pour un objet de connexion à la base de données. (Compte tenu de la nature de JavaScript, je considérerais très dangereux de mélanger quoi que ce soit à un objet construit par le code de la bibliothèque). Donc avec cela vous avez seulement besoin de considérer un module qui exporte deux méthodes. connect = () => Promise et get = () => dbConnectionObject.

Avec un tel module, vous pouvez d'abord vous connecter à la base de données

// runs in boot.js or what ever file your application starts with
const db = require('./myAwesomeDbModule');
db.connect()
    .then(() => console.log('database connected'))
    .then(() => bootMyApplication())
    .catch((e) => {
        console.error(e);
        // Always hard exit on a database connection error
        process.exit(1);
    });

En vol, votre application peut simplement appeler get() lorsqu'elle a besoin d'une connexion DB.

const db = require('./myAwesomeDbModule');
db.get().find(...)... // I have excluded code here to keep the example  simple

Si vous configurez votre module db de la même manière que ce qui suit, non seulement vous aurez un moyen de vous assurer que votre application ne démarrera pas à moins d'avoir une connexion à la base de données, mais vous aurez également un moyen global d'accéder à votre pool de connexion à la base de données. erreur si vous connexion.

// myAwesomeDbModule.js
let connection = null;

module.exports.connect = () => new Promise((resolve, reject) => {
    MongoClient.connect(url, option, function(err, db) {
        if (err) { reject(err); return; };
        resolve(db);
        connection = db;
    });
});

module.exports.get = () => {
    if(!connection) {
        throw new Error('Call connect first!');
    }

    return connection;
}
9
répondu Stewart 2017-08-24 03:39:40

J'ai utilisé generic-pool avec des connexions redis dans mon application - je le recommande fortement. C'est générique et je sais certainement que cela fonctionne avec mysql donc je ne pense pas que vous aurez des problèmes avec et mongo

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

6
répondu ControlAltDel 2012-05-18 18:12:04

Http://mongoosejs.com/docs/api.html

Découvrez la source de La Mangouste. Ils ouvrent une connexion et la lient à un objet modèle, de sorte que lorsque l'objet modèle est requis, une connexion est établie à la base de données. Le conducteur s'occupe de la mise en commun des connexions.

3
répondu srquinn 2012-05-18 21:26:34

Vous devez créer une connexion en tant que service puis la réutiliser en cas de besoin.

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

Mon Application.js échantillon

// 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}`);
  });
});

Et utilisez-le où vous voulez avec

import dbService from "db.service.js"
const db = dbService.db
2
répondu LeeKaD 2017-10-26 20:43:09

J'ai implémenté le code ci-dessous dans mon projet pour implémenter le regroupement de connexions dans mon code afin de créer une connexion minimale dans mon projet et réutiliser la connexion disponible

/* 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");

});
1
répondu Aditya Parmar 2017-10-22 08:18:49

La meilleure approche pour implémenter le regroupement de connexions est que vous devez créer une variable de tableau global qui contient le nom de la base de données avec l'objet de connexion retourné par MongoClient, puis réutiliser cette connexion chaque fois que vous devez contacter La base de données.

  1. Dans votre Serveur.js définir la var globale.dbconnections = [];

  2. Créez un service nommant connectionService.js. Il aura 2 méthodes getConnection et createConnection. Ainsi, lorsque l'utilisateur appellera getConnection (), il trouvera des détails dans la variable de connexion globale et les détails de connexion de retour s'il existe déjà, il appellera createConnection () et retournera les détails de connexion.

  3. Appelez ce service en utilisant db_name et il retournera l'objet de connexion s'il en a déjà d'autre, il créera une nouvelle connexion et vous la renverra.

J'espère que ça aide:)

Voici le connectionService.code 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;
} 
1
répondu RRPatel 2018-03-17 06:58:03