docs.nestjs.com icon indicating copy to clipboard operation
docs.nestjs.com copied to clipboard

[document] mongodb ”Multiple databases“ do not work

Open GongT opened this issue 2 years ago • 6 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Current behavior

Nest can't resolve dependencies of the AppService (?). Please make sure that the argument testModel at index [0] is available in the AppModule context.

Minimum reproduction code

https://github.com/GongT/issues/tree/nest-mongodb-multiple

Steps to reproduce

  1. run a mongodb (I use docker: docker run -it --rm --name mongodb -p 27017:27017 mongo)
  2. npm install
  3. npm run start

Expected behavior

It should work

Package

  • [ ] I don't know. Or some 3rd-party package
  • [ ] @nestjs/common
  • [ ] @nestjs/core
  • [ ] @nestjs/microservices
  • [ ] @nestjs/platform-express
  • [ ] @nestjs/platform-fastify
  • [ ] @nestjs/platform-socket.io
  • [ ] @nestjs/platform-ws
  • [ ] @nestjs/testing
  • [ ] @nestjs/websockets
  • [X] Other (see below)

Other package

No response

NestJS version

8.4.7

Packages versions

[System Information]
OS Version     : Linux 5.18
NodeJS Version : v18.3.0
PNPM Version    : 7.2.1 

[Nest CLI]
Nest CLI Version : 8.2.8 

[Nest Platform Information]
platform-express version : 8.4.7
schematics version       : 8.0.11
mongoose version         : 9.1.1
testing version          : 8.4.7
common version           : 8.4.7
core version             : 8.4.7
cli version              : 8.2.8

Node.js version

18.3.0

In which operating systems have you tested?

  • [ ] macOS
  • [ ] Windows
  • [X] Linux

Other

I'm following the document (here)

https://github.com/GongT/issues/blob/nest-mongodb-multiple/src/app.module.ts#L7-L20

GongT avatar Jul 01 '22 07:07 GongT

I think this is a bug, not only in document. see this

GongT avatar Jul 01 '22 07:07 GongT

Hi @GongT, to do the multi-connection you have to do this:

@Module({
  imports: [
    MongooseModule.forRoot('mongodb://localhost:27017/test1', {
      connectionName: 'mongodb1',
    }),
    MongooseModule.forRoot('mongodb://localhost:27018/test2', {
      connectionName: 'mongodb2',
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

However, for this type of question use the discord support channel.

The NestJS Core team uses GitHub to track bug reports, feature requests, and regressions.

Tony133 avatar Jul 01 '22 07:07 Tony133

please see my repo, this is a BUG, not a question.

I followed document step by step, and got an error.

After digging into source code, I found this may not because missing step in document, but a bug in nest's code.

GongT avatar Jul 01 '22 10:07 GongT

Hi @GongT, i saw your repo, there are implementation errors. I write you the solution below with the files to modify to use the multi-connection with mongoose:

app.module.ts:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { MongooseModule } from '@nestjs/mongoose';
import { test1Schema, test2Schema } from './app.model';

@Module({
  imports: [
    MongooseModule.forRoot('mongodb://localhost:27017/test1', {
      connectionName: 'mongodb1',
    }),
    MongooseModule.forRoot('mongodb://localhost:27018/test2', {
      connectionName: 'mongodb2',
    }),
    MongooseModule.forFeature(
      [{ name: 'collection1', schema: test1Schema }],
      'mongodb1',
    ),
    MongooseModule.forFeature(
      [{ name: 'collection2', schema: test2Schema }],
      'mongodb2',
    ),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

app.service.ts:

import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { DBTest, DBTest2 } from './app.model';

@Injectable()
export class AppService {
  constructor(
    @InjectModel('collection1', 'mongodb1')
    private mongodb1: Model<DBTest>,
    @InjectModel('collection2', 'mongodb2')
    private mongodb2: Model<DBTest2>,
  ) {}

  async getData1() {
    return await this.mongodb1.find().exec();
  }

  async getData2() {
    return await this.mongodb2.find().exec();
  }

  getHello(): string {
    return 'Hello World!';
  }
}

app.model.ts:

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';

@Schema({ collection: 'collection1', timestamps: true })
export class DBTest {
  @Prop({ required: true })
  field: string;
}

export const test1Schema = SchemaFactory.createForClass(DBTest);

@Schema({ collection: 'collection2', timestamps: true })
export class DBTest2 {
  @Prop({ required: true })
  field: string;
}

export const test2Schema = SchemaFactory.createForClass(DBTest2);

app.controller.ts:

import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }

  @Get('data1')
  getData() {
    return this.appService.getData1();
  }

  @Get('data2')
  getData2() {
    return this.appService.getData2();
  }
}

if you need it I also write the docker-compose.

P.s.: In the app.model the collections are better separated into two files, at least I usually do it like this, the choice is yours.

Tony133 avatar Jul 01 '22 16:07 Tony133

Great reply, thanks!

It's missing document about second argument of InjectModel.

Only one line mention this: here. I can't understand it without your reply above.

GongT avatar Jul 02 '22 21:07 GongT

Let's say something can be improved in the documentation or in an example, however if you want to contribute to the documentation feel free to do so and opensource!

Tony133 avatar Jul 03 '22 10:07 Tony133

This issue we can close, it has been corrected through this PR: https://github.com/nestjs/docs.nestjs.com/pull/2434

Tony133 avatar Jan 27 '23 21:01 Tony133