How to reuse mongodb connection in node.js
Asked Answered
S

2

6

I'm using node-mongodb-native driver with mongodb to write a website.

I have a question about how to open mongodb connection once, then use it in collection name users in user.js and collection name posts in comment.js

I want to open db connection in db.js then to insert / save data for users and posts collection

Currently code,my db.js

var Db = require('mongodb').Db,
    Connection = require('mongodb').Connection,
    Server = require('mongodb').Server;
module.exports = new Db(
    'blog', 
    new Server('localhost', Connection.DEFAULT_PORT, {auto_reconnect: true})
);

I used db.js in user.js as follow

var mongodb = require('./db');

function User(user){
  this.name = user.name;
  this.password = user.password;
  this.email = user.email;
};

module.exports = User;

User.prototype.save = function(callback) {//save user information
  //document to save in db
  var user = {
      name: this.name,
      password: this.password,
      email: this.email
  };
  mongodb.close();
  //open mongodb database
  mongodb.open(function(err, db){
    if(err){
      return callback(err);
    }
    //read users collection
    db.collection('users', function(err, collection){
      if(err){
        mongodb.close();
        return callback(err);
      }
      //insert data into users collections
      collection.insert(user,{safe: true}, function(err, user){
        mongodb.close();
        callback(err, user);//success return inserted user information
      });
    });
  });
};

and comment.js

var mongodb = require('./db');

function Comment(name, day, title, comment) {
  this.name = name;
  this.day = day;
  this.title = title;
  this.comment = comment;
}

module.exports = Comment;

Comment.prototype.save = function(callback) {
  var name = this.name,
      day = this.day,
      title = this.title,
      comment = this.comment;
  mongodb.open(function (err, db) {
    if (err) {
      return callback(err);
    }
    db.collection('posts', function (err, collection) {
      if (err) {
        mongodb.close();
        return callback(err);
      }
      //depend on name time and title add comment
      collection.findAndModify({"name":name,"time.day":day,"title":title}
      , [ ['time',-1] ]
      , {$push:{"comments":comment}}
      , {new: true}
      , function (err,comment) {
          mongodb.close();
          callback(null);
      });   
    });
  });
};
Sort answered 15/7, 2013 at 6:12 Comment(1)
Your question does not sound like a question. What is not happening, and please post exact challenge you are facing.Fransiscafransisco
F
8

You can connect once, and then reuse it as many times as you want:

var mongodb = require('mongodb');
var events = require('events');
var event = new events.EventEmitter();
var access = new mongodb.Server(host, port, { });
var client = null;

new mongodb.Db('YOUR DATABASE', access, { safe: true, auto_reconnect: true }).open(function (err, c) {
  if (!err) {
    client = c;
    console.log('database connected');
    event.emit('connect');
  } else {
    console.log('database connection error', err);
    event.emit('error');
  }
});

exports.get = function(fn) {
  if(client) {
    fn(client);
  } else {
    event.on('connect', function() {
      fn(client);
    });
  }
};

And then reuse it:

var db = require('./db');
var items;
db.get(function(client) {
  items = new mongodb.Collection(client, 'collection');
});

// then anywhere in your code
db.get(function() {
  // items.find({ ...
});
Fransiscafransisco answered 15/7, 2013 at 8:38 Comment(9)
My answer does exactly what you've just asked. Please read it.Fransiscafransisco
Have you tried to understand and apply ideas and code from answer above? If no, please do so. If yes - please share what is exactly failing in your case.Fransiscafransisco
Because you need first to actually connect to database, before you do any of your logic.Fransiscafransisco
Connection happens asynchronously, so if you call .open - it is not going to be available straight away after.Fransiscafransisco
I've improved the code above, so please review it, and let me know results of your attempts. Async singleton pattern is used.Fransiscafransisco
no its not working, I applied what you updated in my code in once branch, can you test in your local computerSort
I cannot run your code at the moment. Could you provide at least exception, where it happens and so on? You can make comments directly in once branch.Fransiscafransisco
Thanks, I put comment hereSort
You copied code wrong. var ee = require('events').EventEmitter(); is wrong as not creating EventEmitter. Please refer to answer above or change line to: var ee = new (require('events').EventEmitter);Fransiscafransisco
A
2

Accepted answer is 3 year old and it wont work with latest node-mongodb-native driver. I have modified @moka answer and added some delay and retry logic.

var MongoClient = require('mongodb').MongoClient;
var events = require('events');
var event = new events.EventEmitter();
var database = null;
var retries = 0;
var delay = 300;

setTimeout(connect,delay);

// Use connect method to connect to the server
function connect(){
    MongoClient.connect(process.env.MONGODB_URL, function(err, db) {
        if(!err){
            console.log("Connected successfully to server");
            database = db;
            event.emit('dbconnect');

        } else {
            if(retries < 4){
                console.log('Retrying to connect db %s', retries++);
                setTimeout(connect,delay);
            } else {
                console.log('Unable to connect db');
            }
        }
    });
}


exports.get = function(fn) {
    if(database !== null) {
        fn(database);
    } else {
        event.on('dbconnect', function() {
            fn(database);
        });
    }
};
Agraffe answered 22/4, 2017 at 9:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.