4

Is there a way to connect multiple MongoDB connections per module?

app.module.ts

@Module({
  imports: [
    MongooseModule.forRoot('mongodb://localhost/masterDB'),
    UserModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule { }

Similarly, can we define another connection in another module which is a child of app.module?

child.module.ts

@Module({
  imports: [
    MongooseModule.forRoot('mongodb://localhost/childDB'),
    MongooseModule.forFeature([{ name: 'child', schema: ChildSchema }]),
  ],
  controllers: [ChildController],
  providers: [ChildService],
})
export class ChildModule { }

Or any other way to access different databases at once.

Thanks in advance!

3 Answers 3

13

[SOLVED March 2021]

Here you'll find the solution:

https://www.learmoreseekmore.com/2020/04/nestjs-multiple-mongodb-databases.html

import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { studentSchema } from './schemas/myworld/student.schema';
import { animalSchema } from './schemas/wildlife/animal.schema';

@Module({
  imports: [
    MongooseModule.forFeature([
      {
        name: 'Student',
        schema: studentSchema,
        collection: 'Student',
        
      },
    ],'myWorldDb'),
    MongooseModule.forFeature([
      {
        name: 'Animals',
        schema: animalSchema,
        collection: 'Animals'
      }
    ],'wildLifeDb'),
    MongooseModule.forRoot(
      'mongodb+srv://<userName>:<password>@cluster0-igk.mongodb.net/MyWorld?retryWrites=true&w=majority',
      {
        connectionName: 'myWorldDb'
      }
    ),
    MongooseModule.forRoot(
      'mongodb+srv://<username>:<password>@cluster0-igk.mongodb.net/WildLife?retryWrites=true&w=majority',
      {
        connectionName: 'wildLifeDb'
      }
    )

  ],
  controllers: [],
  providers: [],
})
export class AppModule {}
Sign up to request clarification or add additional context in comments.

3 Comments

Happy to be helpfull ^^
I get this error: ERROR [ExceptionHandler] Nest can't resolve dependencies of the TestService (?, AnimalsModel). Please make sure that the argument StudentModel at index [0] is available in the TestService context. Do you know why?
It has been a while but I found the same issue and figured out that you also need to specify the connectionName when you use the @InjectModel
8

You have to do it manually you have to use a providers file:

mongoose.providers.ts

import * as mongoose from 'mongoose';

export const mongooseProviders = [
  {
    provide: 'MASTER_CONNECTION',
    useFactory: (): Promise<typeof mongoose> =>
    // This mongoose.connect never working for multples DB connection
    // mongoose.connect('mongodb://localhost/masterDB'),
    // Following is working fine and tested by me
    mongoose.createConnection('mongodb://localhost/masterDB'),
  },
  {
    provide: 'CHILD_CONNECTION',
    useFactory: (): Promise<typeof mongoose> =>
    // This mongoose.connect never working for multples DB connection
    // mongoose.connect('mongodb://localhost/masterDB'),
    // Following is working fine and tested by me
      mongoose.createConnection('mongodb://localhost/ChildDB'),
  },
];

mongoose.module.ts

import { Module } from '@nestjs/common';
import { mongooseProviders } from './mongoose.providers';

@Module({
  providers: [...mongooseProviders],
  exports: [...mongooseProviders],
})
export class MongooseModule {}

model.providers.ts

import { Connection } from 'mongoose';
import { ChildSchema } from './schemas/child/child.schema';
import { MasterSchema } from './schemas/master/master.schema';

export const modelProviders = [
  {
    provide: 'CHILD_MODEL',
    useFactory: (connection: Connection) => connection.model('Child', ChildSchema),
    inject: ['CHILD_CONNECTION'],
  },
  {
    provide: 'MASTER_MODEL',
    useFactory: (connection: Connection) => connection.model('Master', MasterSchema),
    inject: ['MASTER_CONNECTION'],
  },
];

And on the constructor instead of using @InjectModel you use @Inject:

@Injectable
export Class ModelService {
  constructor(@Inject('MASTER_MODEL') private masterModel: Model<Master>) {}
...

Note: in the module you provide the service you should import the MongooseModule and put as provider modelProviders.

4 Comments

Hi, this seems the right answer to the question, ill mark it as "answered". But these providers are a singleton, right? Can we have a dynamic connections name? e.g. I may have multiple dynamic children (tenants) database - childDB1, childDB2, childDB3 ... and so on.
yes you can you will have to use a custom provider for each conection docs.nestjs.com/fundamentals/custom-providers take a look at this
hey, I think my above comment was not clear. I have a situation - I have users collection in my MasterDB and for each user registered in the app I need to create and use ChildDB dynamically e.g. user1 in MasterDB will have its own user1DB which can be accessed by some particular modules only. How can I update the MongoDB uri for each of those modules?
just change it in the mongoose.providers.ts in its factory
4

Post above from RalphJS really helped, but it only was using one connection for everything. Had to change 1 thing in model.providers.ts: instead of mongoose.connect you have to use mongoose.createConnection

model.providers.ts

import * as mongoose from 'mongoose';

export const mongooseProviders = [
  {
    provide: 'MASTER_CONNECTION',
    useFactory: async (): Promise<unknown> =>
      await mongoose.createConnection('mongodb://localhost/masterDB'),
  },
  {
    provide: 'CHILD_CONNECTION',
    useFactory: async (): Promise<unknown> =>
      await mongoose.createConnection('mongodb://localhost/childDB'),
  },
];

https://mongoosejs.com/docs/connections.html#multiple_connections

Comments

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.