Guide to connect to multiple databases using Mongoose

in voilk •  4 months ago

    People who are used to building apps with Mongo and Nodejs should be familiar with Mongoose which is an ORM for MongoDB. Though there are other competitive ORMs available, it is one of the most popular and efficient ORMs for Mongo connectivity. When I build my applications, my first choice would be to use a Mongo database. The main reason is that I have used it on many apps and find it comfortable to use.

    I recently had a requirement to establish connections and work on multiple Mongo databases within my backend application. More like switching between multiple databases based on user requests. There were a few solutions that I came across online and finally fixed with a solution.

    • Have multiple connection strings saved in the config file and switch between them or connect to each one of them. This can work if we are working only on a few databases.
    • Opening and closing connections for every request.
    • Have a single connection to a master database and switch to other databases internally using useDb feature.

    image.png

    Source

    I solved my need with the third solution. In my case, I was using models and I wanted them to be common for all the databases. That's why I came up with this solution and it works well. I'm going to walk through the code step by step.

    Note: I'm assuming that the readers are familiar with Nodejs and MongoDB. I'm not going to be covering the complete code of the backend application.

    Step 1: Creating the db.js file

    This file will have basic connection information to the database. I usually keep this file separately and establish the connection only by including this file in my main file. It helps in modularizing the code.

    const  mongoose = require('mongoose');
    
    const database = 'mongodb://localhost:27017/primary';
    
    mongoose.connect(database, {});
    
    const  db = mongoose.connection;
    
    // Check DB Connection
    db.once('open', () => {
    
    // eslint-disable-next-line no-console
    console.log('Connected to MongoDB');
    
    });
    
    // Check for DB errors
    db.on('error', (err) => {
    
    // eslint-disable-next-line no-console
    console.log('DB Connection errors', err);
    });
    
    module.exports = mongoose;
    
    

    If you notice I would have primary as my database. This is the primary database that I would be connecting to. Only from that database, I would be switching to other databases whenever needed.

    Step 2: Creating my model file client.js

    The next step would be to create my model file that will have the schema of my collection. I wanted to have a single model file created for a collection that I would be using across all the databases.

    const  mongoose = require('mongoose');
    
    // eslint-disable-next-line prefer-destructuring
    const  Schema = mongoose.Schema;
    
    const  clientSchema = new  Schema(
    {
    clientNumber: {
    type:  Number,
    required:  true,
    },
    clientName: {
    type:  String,
    required:  true,
    },
    },
    { versionKey:  false, minimize:  false },
    );
    
    const  client = async (db) => {
    const myDB = mongoose.connection.useDb(db);
    const  Client = myDB.model('Client',clientSchema);
    return  Client;
    };
    
    module.exports = { client };
    
    

    In the above model file, I have a schema for the Client with two fields in that. If you look at the code, I have a function towards the end of the code that accepts the database as the input parameter and gives the model as the output parameter.

    Step 3: My main.js file

    In my main.js file, I have the below code to create a new client. I have included both of the above files in this main file. I wanted to test it out by creating a client on multiple databases at the same time.

    require('./db');
    const { client } = require('./client');
    
    // Saving to primary database
    (async () => {
    const  Client = await  client('primary');
    const  c = new  Client();
    c.clientNumber = 1234;
    c.clientName = 'Test Client';
    await  c.save();
    })();
    
    // Saving to secondary1 database
    (async () => {
    const  Client = await  client('secondary1');
    const  c = new  Client();
    c.clientNumber = 1234;
    c.clientName = 'Test Client';
    await  c.save();
    })();
    
    // Saving to secondary2 database
    (async () => {
    const  Client = await  client('secondary2');
    const  c = new  Client();
    c.clientNumber = 1234;
    c.clientName = 'Test Client';
    await  c.save();
    })();
    
    

    As we all know Nodejs is asynchronous by default, when we execute the main.js file, it executes all the 3 functions at the same time creating the same entry on 3 different databases. This is an example to show how we can pass the database name as a parameter to the model and perform operations on specific models in each database.


    If you like what I'm doing on Hive, you can vote me as a witness with the links below.

    Vote @balaz as a Hive Witness

    Vote @kanibot as a Hive Engine Witness



      Authors get paid when people like you upvote their post.
      If you enjoyed what you read here, create your account today and start earning FREE VOILK!