Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a mongodb connection provider in Nestjs

I am trying to create a database connection provider in Nestjs for MongoDB.

I inspected the user.controller.ts and mongoDbProvider by putting breakpoints and found that the controller gets before the database connection is made. How do I make a database connection before the controllers get initialized?

Nest.js documentation says that useFactory method will run before any other module that depends on it.

src/mongo-db/mongodb.provider.ts

import { MongoClient } from "mongodb";
import { MONGODB_PROVIDER } from "../constants";

export const mongoDbProviders = [
  {
    provide: MONGODB_PROVIDER,
    useFactory: async () => {
      MongoClient.connect('mongodb://localhost:27017',
        { useUnifiedTopology: true },
        (error, client) => {
          return client.db('nestjs-sample');
        });
    }
  },

];

src/mongo-db/mongo-db.module.ts

import { mongoDbProviders } from './mongo-db.providers';

@Module({
  providers: [...mongoDbProviders],
  exports: [...mongoDbProviders],
})
export class MongoDbModule {

}

src/constants.ts

export const MONGODB_PROVIDER = 'MONGODB_CONNECTION';

I imported MongoDbModule into user.module.ts

src/user/user.module.ts

import { Module } from '@nestjs/common';
import { UserController } from './user.controller';
import { UserService } from './user.service';
import { MongoDbModule } from 'src/mongo-db/mongo-db.module';

@Module({
  imports: [MongoDbModule],
  controllers: [UserController],
  providers: [UserService]
})
export class UserModule {}

Here I injected the db from mongoDbProvider into UserController constructor. But the constructor runs before db connection.

src/user/user.controller.ts

import { Controller, Post, Req, Get, Res, Inject } from '@nestjs/common';
import { Request, Response } from "express";
import { MONGODB_PROVIDER } from 'src/constants';

@Controller('users')
export class UserController {

  constructor(@Inject(MONGODB_PROVIDER) private readonly db: any) {

  }

  @Post()
  async create(@Req() request: Request, @Res() response: Response) {
    this.db.collection('users').insertOne(request.body, (err, result) => {
      if (err) {
        response.status(500).json(err);
      } else {
        response.status(201);
        response.send(result);
      }
    });
  }

  @Get()
  get(@Req() request: Request, @Res() response: Response) {
    response.status(400).json({
      message: 'kidilam service'
    });
  }

}
like image 201
diffuse Avatar asked Feb 21 '20 20:02

diffuse


People also ask

What is schema in NestJS?

Schemas are used to define Models. Models are responsible for creating and reading documents from the underlying MongoDB database. Schemas can be created with NestJS decorators, or with Mongoose itself manually.

Which database is best for NestJS?

Nest uses TypeORM because it's the most mature Object Relational Mapper (ORM) available for TypeScript. Since it's written in TypeScript, it integrates well with the Nest framework.

Is NestJS better than Express?

Nest offers a ready-to-use application architecture using controllers, providers, and modules. This enables developers and teams create applications that are simple to test and maintain. Express does not require a specific structure, which can provide flexibility for small or one-person development teams.


1 Answers

I found the solution. It is because the useFactory expects a promise because it is an async function. So I wrapped the MongoClient.connect() inside a Promise to resolve the database connection. Now it waits until the promise is resolved before initializing any modules that depend on it.

import { MongoClient } from "mongodb";
import { MONGODB_PROVIDER } from "../constants";

export const mongoDbProviders = [
  {
    provide: MONGODB_PROVIDER,
    useFactory: async () => new Promise((resolve, reject) => {
      MongoClient.connect('mongodb://localhost:27017',
      { useUnifiedTopology: true },
      (error, client) => {
        if (error) {
          reject(error);
        } else {
          resolve(client.db('nestjs-sample'));
        }
      });
    })
  },
];
like image 128
diffuse Avatar answered Oct 13 '22 21:10

diffuse