89

In so many introductory examples of using MongoDB, you see code like this:

var MongoClient = require('mongodb').MongoClient;
MongoClient.connect("mongodb://localhost:port/adatabase", function(err, db)
{
    /* Some operation... CRUD, etc. */
    db.close();
});

If MongoDB is like any other database system, open and close operations are typically expensive time-wise.

So, my question is this: Is it OK to simply do the MongoClient.connect("... once, assign the returned db value to some module global, have various functions in the module do various database-related work (insert documents into collections, update documents, etc. etc.) when they're called by other parts of the application (and thereby re-use that db value), and then, when the application is done, only then do the close.

In other words, open and close are done once - not every time you need to go and do some database-related operation. And you keep re-using that db object that was returned during the initial open\connect, only to dispose of it at the end, with the close, when you're actually done with all your database-related work.

Obviously, since all the I/O is asynch, before the close you'd make sure that the last database operation completed before issuing the close. Seems like this should be OK, but i wanted to double-check just in case I'm missing something as I'm new to MongoDB. Thanks!

3
  • Also check this, may help you Commented Sep 6, 2013 at 6:45
  • Interesting.... Yes, helpful; thank you very much! Commented Sep 6, 2013 at 13:28
  • This is a duplicate question: "stackoverflow.com/questions/10656574/…" Commented Mar 7, 2022 at 18:44

3 Answers 3

71

Yes, that is fine and typical behavior. start your app, connect to db, do operations against the db for a long time, maybe re-connect if the connection ever dies unexpectedly, and then just never close the connection (just rely on the automatic close that happens when your process dies).

Sign up to request clarification or add additional context in comments.

5 Comments

Also, you get 5 pooled connections by default with node-mongodb-native. Check out the docs on poolSize.
Thanks a lot for confirming my suspicions, Peter - appreciate it!
I followed the solution stackoverflow.com/a/24634454/3994271 which does the same thing as mentioned in this answer. But,how can we automatically reconnect if the connection ever dies unexpectedly?
This is a very helpful answer, however it could be much more helpful if it provided a method for keeping the connection alive in case it dies.
Check out @MihirPatel's answer below to see how to have your mongo client reconnect easily.
15

mongodb version ^3.1.8

Initialize the connection as a promise:

const MongoClient = require('mongodb').MongoClient
const uri = 'mongodb://...'
const client = new MongoClient(uri)
const connection = client.connect() // initialized connection

And then call the connection whenever you wish you perform an action on the database:

    // if I want to insert into the database...
    const connect = connection
    connect.then(() => {
        const doc = { id: 3 }
        const db = client.db('database_name')
        const coll = db.collection('collection_name')
        coll.insertOne(doc, (err, result) => {
            if(err) throw err
        })
    })

2 Comments

The code example made things a lot clearer, thank you.
Wouldn't it be better to resolve the promise & then store the MongoClient object in the connect var, instead of resolving each time we access db ?
5

The current accepted answer is correct in that you may keep the same database connection open to perform operations, however, it is missing details on how you can retry to connect if it closes. Below are two ways to automatically reconnect. It's in TypeScript, but it can easily be translated into normal Node.js if you need to.

Method 1: MongoClient Options

The most simple way to allow MongoDB to reconnect is to define a reconnectTries in an options when passing it into MongoClient. Any time a CRUD operation times out, it will use the parameters passed into MongoClient to decide how to retry (reconnect). Setting the option to Number.MAX_VALUE essentially makes it so that it retries forever until it's able to complete the operation. You can check out the driver source code if you want to see what errors will be retried.

class MongoDB {
    private db: Db;

    constructor() {
        this.connectToMongoDB();
    }

    async connectToMongoDB() {
        const options: MongoClientOptions = {
            reconnectInterval: 1000,
            reconnectTries: Number.MAX_VALUE
        };

        try {
            const client = new MongoClient('uri-goes-here', options);
            await client.connect();
            this.db = client.db('dbname');
        } catch (err) {
            console.error(err, 'MongoDB connection failed.');
        }
    }

    async insert(doc: any) {
        if (this.db) {
            try {
                await this.db.collection('collection').insertOne(doc);
            } catch (err) {
                console.error(err, 'Something went wrong.');
            }
        }
    }
}

Method 2: Try-catch Retry

If you want more granular support on trying to reconnect, you can use a try-catch with a while loop. For example, you may want to log an error when it has to reconnect or you want to do different things based on the type of error. This will also allow you to retry depending on more conditions than just the standard ones included with the driver. The insert method can be changed to the following:

async insert(doc: any) {
    if (this.db) {
        let isInserted = false;

        while (isInserted === false) {
            try {
                await this.db.collection('collection').insertOne(doc);
                isInserted = true;
            } catch (err) {
                // Add custom error handling if desired
                console.error(err, 'Attempting to retry insert.');

                try {
                    await this.connectToMongoDB();
                } catch {
                    // Do something if this fails as well
                }
            }
        }
    }
}

1 Comment

btw! MongoClientOptions no longer has: reconnectInterval: 1000,& reconnectTries: Number.MAX_VALUE

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.