8

I want to make use of the promises feature where in I can connect to mongodb synchronously and I can reuse the connection by passing it on to different modules.

Here is something that I came up with

class MongoDB {

    constructor(db,collection) {      
      this.collection = db.collection(collection);
    }

    find(query, projection) {
        if(projection)
            return this.collection.find(query, projection);
        else
            return this.collection.find(query);
    }
}

class Crew extends MongoDB {

    constructor(db) {        
        super(db,'crews');
    }

    validate() {

    }
}

I want to setup a connection somewhere in my initial code like the one below and then reuse the connection for different classes, just like how mongoose or monk does but using only the node-mongodb-native package.

MongoClient.connect(url)
          .then( (err,dbase) => {
                global.DB = dbase;
              });


var Crew = new CrewModel(global.DB);


Crew.find({})
   .then(function(resp) {
      console.log(resp);
   });

Right now, the db returns undefined inside the main MongoDB class and am not able to debug this one out through google or the documentation.

Edit: I had assumed that a promise was synchronous but that is not the case.

3 Answers 3

7

To reuse the connection I would create a module like this.

module.exports = {

    connect: function(dbName,  callback ) {
       MongoClient.connect(dbName, function(err, db) {

       _db = db;
       return callback( err );
    });
},

     getDb: function() {
        return _db;
     }
};

After that you can connect to the database before starting your application

MongoConnection.connect("mongodb://localhost:27017/myDatabase", function(err){
    app.listen(3000, function () {
        // you code
    });
});

Considering you created the module in a js file you can simply use require to get the databaseConnection

var dbConnection = require("./myMongoConnection.js");

and to get the connection use

var db = MongoConnection.getDb();
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, there was a flaw in my question. I assumed that a promise was synchronous hence some mistake in my code but thanks for this piece of information as it very useful for me.
1

Another option using ES6 classes creates a singleton object that you can access repeatedly. It's inspired by @user3134009's answer here.

const EventEmitter = require('events');
const MongoClient = require('mongodb').MongoClient;
const config = require('config');

let _db = null;

class MongoDBConnection extends EventEmitter {
  constructor() {
    super();
    this.emit("dbinit", this);
    if (_db == null) {
      console.log("Connecting to MongoDB...");
      MongoClient.connect(config.dbs.mongo.url, config.dbs.mongo.options, 
(err, db) => {
        if (err) {
           console.error("MongoDB Connection Error", err);
          _db = null;
        } else {
          console.log("Connected to MongoDB", config.dbs.mongo.url);
          db.on('close', () => { console.log("MongoDB closed", arguments); _db = null; });
          db.on('reconnect', () => { console.log("MongoDB reconnected", arguments); _db = db; });
          db.on('timeout', () => { console.log("MongoDB timeout", arguments); });
          _db = db;
          this.emit('dbconnect', _db);
        }
      });
    }
  }
  getDB() {
    return _db;
  }
}
module.exports = new MongoDBConnection();

Comments

1

I have been struggling with this problem for a while, and in particular with setting up and persisting MongoDb connection in AWS lambda functions across invocations. Thanks to @toszter answer I've finally come up with the following solution:

const mongodb = require('mongodb');
const config  = require('./config.json')[env];
const client  = mongodb.MongoClient;

const mongodbUri = `mongodb://${config.mongo.user}:${config.mongo.password}@${config.mongo.url}/${config.mongo.database}`;


const options = {
  poolSize: 100, 
  connectTimeoutMS: 120000, 
  socketTimeoutMS: 1440000
 };

// connection object
let _db = null;

class MongoDBConnection {
  constructor() {}

  // return a promise to the existing connection or the connection function
  getDB() {
    return (_db ? Promise.resolve(_db) : mConnect());
  }
}

module.exports = new MongoDBConnection();

// transforms into a promise Mongo's client.connect
function mConnect() {
  return new Promise((resolve, reject) => {
    console.log('Connecting to Mongo...');
    client.connect(mongodbUri, options, (error, db) => {
      if (error)  {
        _db = null;
        return reject(error);
      }
      else {
        console.log('Connected to Mongo...');
        _db = db;
        resolve(db);
      }
    });
  });
}

To use it in a controller or app.js:

  const mongoConfig  =  require('mongoConfig');
  mongoConfig.getDB()
    .then(db => db.collection('collection').find({}))
    .catch(error => {...});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.