Alex
Alex

Reputation: 418

Mongoose: handling multiple databases when working with one model

What I want is to have arbitrary databases (50 for example) with the same collections (same schemas, exact models, different data) and 1 nodejs (expressjs + mongoose) web app.

Example simplified case:

I have:

What behaviour I want to achieve:

So I just want an abstraction. I pass db name to mongoose and continue to work with the User model (as we all usually do when having single DB connection) and mongoose, if needed, creates connection (if it's the first request to the specific db), keeps it alive for next requests in connection pool and etc.

What's the most simple and efficient way to accomplish that?

Thank's in advance!

Upvotes: 1

Views: 1452

Answers (2)

Ahmed Ibrahim
Ahmed Ibrahim

Reputation: 517

This is how I implemented my project:

// config/db.ts
import {createConnection} from 'mongoose'

const MONGO_URI = process.env.MONGO_URI

if (!MONGO_URI)
  throw new Error(
    'Please define the MONGO_URI environment variable inside .env'
  )

const connections: any = {}

async function db(dbName: string) {
  if (connections[dbName]) {
    return connections[dbName]
  } else {
    connections[dbName] = createConnection(`${MONGO_URI}/${dbName}`)
    return connections[dbName]
  }
}

export default db




// models/Test.ts
import { Schema } from 'mongoose'

export interface ITest {
  _id: Schema.Types.ObjectId
  name: string
  createdAt?: Date
}

const testSchema = new Schema<ITest>(
  {
    name: { type: String, required: true },
  },
  { timestamps: true }
)

export default testSchema




// pages/api/test.ts
import nc from 'next-connect'
import db from '../../config/db'
import testSchema from '../../models/Test'

const handler = nc()

handler.get(
  async (req: NextApiRequestExtended, res: NextApiResponseExtended) => {
    try {
      const conn = await db(req.headers['x-db-key'])
      const model = await conn.model('Test', testSchema)

      const data = await model.find({})

      res.send(data)
    } catch (error: any) {
      res.status(500).json({ error: error.message })
    }
  }
)

export default handler

Upvotes: 0

bentesha
bentesha

Reputation: 948

IMHO, while this is possible with MongoDB, I wouldn't advise maintaining a separate database for each domain, especially if you are expecting to have a huge number of them. Have you considered a multi-tenant model instead?

The sample code below adds user 'Alex' into two different databases, "domainOne" and "domainTwo". Hope this helps

var mongoose = require('mongoose');
var personSchema = { name: String, domain : String };
var baseUri = 'mongodb://localhost/';

domains.forEach((domain) => {
    var conn = mongoose.createConnection(baseUri + domain, (error) => {
    if(error){
        console.log('Ups! Database connection failed!');
        return;
    }
    //Use the connection object to create your models,
    //instead the mongoose object
    //so that our data is saved into the database
    //associated with this connection
    var Person = conn.model('Person', personSchema);

    //Lets add user 'Alex' into the database
    (new Person({name : 'Alex', domain : domain })).save((error) => {
        if(error){
            console.log('Ups! Could not save person');
        } else {
            conn.close();
        }
    });
    });
});

Upvotes: 1

Related Questions