Proper Way To Connect MongoDb — NodeJs

Eren Yatkin
Oct 12 · 5 min read
Image for post
Image for post

Hey folks! I would like to ask you a question. What is the main thing of an application ? Well, just as you thought, it can be anything. Actually the goal of an application defines that thing. Therefore I will ask you a more specific question. What is the main thing of an application, if it’s built to do heavy CRUD operations ?

In this case, database is the main thing of that application. I got you there, right? Most applications, microservices, cronjobs etc. do CRUD operations in their lifecycles. I work as full stack software engineer in Istanbul and wrote tons of CRUD operations. Finally, I found a proper way to connect MongoDb in NodeJs (with Mongoose of course.). Before we dive deep into this, we need couple of things to do.

What do we need?

As the title said, we need

  • NodeJs LTS — 10^
  • MongoDb
  • Docker
  • Visual Studio Code (with beloved Lexcuim Black theme)

I guess these are the needs for now. Let’s use them to do what we came to do.

Getting Ready To Start

First thing first, we need to install NodeJs. Open this link in another tab to download LTS version of NodeJs.

Then we need to prepare MongoDb. Therefore we need to install Docker on our machines, because it is the easy way to manage MongoDb. Open this link to download Docker and run the code placed below after installation is done.

If you do not want to install Docker, we can simply use MongoDb Atlas. Open this link to create an account.

Alright, we are ready to go!

Follow these steps to create an environment

  • create empty folder to work in
  • Init a nodeJs project, -y will skip the form.
  • create index.js
  • edit package.json as shown
  • install dependencies
  • open up index.js, lets define dependencies and our functions
const clients = {};
let connectionTimeout;
module.exports.init = () => {};module.exports.closeConnections = () => {};module.exports.getClients = () => {};
  • well, we defined the functions, let’s fill them up. First we need to create a connection instance. We do this because in the future we may need to make second or third connection to another mongoDb database. Do not ask why, you will eventually encounter with this problem.
    clients.mongoInstance = mongoInstance;
};
  • we created our mongoDb connection with Mongoose and I will explain why we passed these options. Also we saved that connection in an object to import and use later.
  • keepAlive: true, if your app will run for a long time. It is true by default if you are using mongoose^5.2.0
  • autoReconnect: true, if the connection interrupted, mongoose will try to connect instead of throwing error. We will handle this functionallity manually.
  • reconnectTries: number, defines that how many times should mongoose try to connect,
  • reconnectInterval: number(miliseconds), defines that how many miliseconds does mongoose need to establish connection in.

Some events will be fired acording to the state of the connection. It’ s better to listen them to take actions. Because this module will manage the entire connection flow. We need to know any interruptions or connection losses. Let’s see what are these events.

  • conencted, fired after successful connection
  • disconnected, fired if the connection drops
  • reconnected, fired after successful reconnection
  • close, fired after the connection closes by you

Now let’s add an event listener, I changed the init() function like below and added the handler. I prefer RO-RO(recieve object — return object) approach when developping an NodeJs application. Because it improves readability of the code.

    conn.on('disconnected', () => {
console.log('Database - Connection status: disconnected');
});
conn.on('reconnected', () => {
console.log('Database - Connection status: reconnected');
});
conn.on('close', () => {
console.log('Database - Connection status: close ');
});
}
module.exports.init = () => {
const mongoInstance = mongoose.createConnection(config.DATABASE.HOST, {
useNewUrlParser: true,
keepAlive: true,
autoReconnect: true,
reconnectTries: 3,
reconnectInterval: 5000,
});
clients.mongoInstance = mongoInstance;
instanceEventListeners({ conn: mongoInstance });
};

Now what? As I said above, we will handle the reconenction procedure by ourselves. Follow the code below, I just simply added a timeout function. In my case I can live with few connection drops. I mean is it ok to lose connection as long as it reconnects in certain amount of time.

Let’s add that timeout function to see how it goes,

function instanceEventListeners({ conn }) {
conn.on('connected', () => {
console.log('Database - Connection status: connected');
clearTimeout(connectionTimeout);
});
conn.on('disconnected', () => {
console.log('Database - Connection status: disconnected');
throwTimeoutError();
});
conn.on('reconnected', () => {
console.log('Database - Connection status: reconnected');
clearTimeout(connectionTimeout);
});
conn.on('close', () => {
console.log('Database - Connection status: close ');
clearTimeout(connectionTimeout);
});
}
module.exports.init = () => {
const mongoInstance = mongoose.createConnection(config.DATABASE.HOST, {
useNewUrlParser: true,
keepAlive: true,
autoReconnect: true,
reconnectTries: 3,
reconnectInterval: 5000,
});
clients.mongoInstance = mongoInstance;
instanceEventListeners({ conn: mongoInstance });
};

a-ha, we did it! What we have now? Let’s break it down,

  • We defined connectionTimeout null because we want to start the timeout when specific event which is disconnected fired,
  • When we get a disconnected event, timeout will start, then reconnection procedure will try to reconnect according to the values we defined. The math is simple here, multiply the reconnection interval with reconnection try and sum with little buffer to find perfect timeout values. setTimeout() will track of the time while mongoose tries to connect. If the connection establishes again we need to clear the timeout, because we do not want to throw an error after that. By the way clearTimeout will not affect anything when connectionTimeout set to null or undefined.

We left some nice to haves, lets fill them. I would like to manage the flow of closing the connection how I manage the opening. Because if you run your application in Kubernetes shutting down an application gracefully is always the best practise.

  • forOwn() will loop the object keys, and every connection we just simply called close()

What about using the connection? Lets add it and we are done!

With piece of function you can import and use the connections you created.

Finally

We reached the end and created ourselves a beautiful Mongoose connection handler. This is the most suitable way we found for our microservices. Handling the connection state and knowing whats going on will improve the quality of your services.

TL;DR; link

For full code checkout this link,

For introduction to Docker checkout this link,

For Ro-Ro approach checkout this link,

Till next time, stay cool!

Enjoyed this article? If so, get more similar content by subscribing to Decoded, our YouTube channel!

JavaScript In Plain English

New JavaScript + Web Development articles every day.

Eren Yatkin

Written by

Fullstack software developer who wants to share his knowledge across the universe. http://www.erenyatkin.com

JavaScript In Plain English

New JavaScript + Web Development articles every day.

Eren Yatkin

Written by

Fullstack software developer who wants to share his knowledge across the universe. http://www.erenyatkin.com

JavaScript In Plain English

New JavaScript + Web Development articles every day.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store