Sling Academy
Home/Node.js/How to Integrate MongoDB with NestJS

How to Integrate MongoDB with NestJS

Last updated: December 31, 2023

Overview

NestJS, a powerful Node.js framework, can be effectively integrated with MongoDB, a popular NoSQL database. This tutorial guides you through the process step by step.

By the end of this tutorial, you will know how to set up a NestJS project configured to connect with a MongoDB database, use Mongoose for schema models, and perform CRUD operations. We’ll take a practical approach, walking through essential steps and providing code snippets to illustrate the integration.

Prerequisites:

  • Node.js installed
  • NPM or Yarn as a package manager
  • Basic knowledge of TypeScript and NestJS
  • MongoDB account and database set up

Setting up a NestJS Project

npm i -g @nestjs/cli
nestjs new project-name

This command installs the NestJS CLI globally and scaffolds a new project.

Installing Mongoose and NestJS/Mongoose

npm install @nestjs/mongoose mongoose

These packages provide the necessary tools to integrate MongoDB via Mongoose in your application.

Configuring the MongoDB Connection

import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';

@Module({
  imports: [
    MongooseModule.forRoot('mongodb+srv://your-db-uri', {
      useNewUrlParser: true,
      useUnifiedTopology: true,
    }),
  ],
})
export class AppModule {}

Replace ‘your-db-uri’ with your actual MongoDB URI. The options `useNewUrlParser` and `useUnifiedTopology` are included for compatibility.

Defining a Schema Model

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

@Schema()
export class Cat extends Document {
  @Prop({ required: true })
  name: string;

  @Prop()
  age: number;

  @Prop()
  breed: string;
}

export const CatSchema = SchemaFactory.createForClass(Cat);

This code defines a simple `Cat` schema with the `@Prop` decorator to denote the properties.

Creating a Module

import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { Cat, CatSchema } from './schemas/cat.schema';

@Module({
  imports: [
    MongooseModule.forFeature([{ name: Cat.name, schema: CatSchema }]),
  ],
})
export class CatsModule {}

The `CatsModule` incorporates the `Cat` schema, making it available within this specific module.

Service Layer

import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { Cat } from './schemas/cat.schema';

@Injectable()
export class CatsService {
  constructor(@InjectModel(Cat.name) private catModel: Model) {}

  async create(createCatDto: { name: string; age: number; breed: string }): Promise {
    const createdCat = new this.catModel(createCatDto);
    return createdCat.save();
  }

  async findAll(): Promise<Cat[]> {
    return this.catModel.find().exec();
  }
}

The `CatsService` utilizes the model to provide create and find operations for the cat entities.

Controller Layer

import { Controller, Get, Post, Body } from '@nestjs/common';
import { CatsService } from './cats.service';
import { Cat } from './schemas/cat.schema';

@Controller('cats')
export class CatsController {
  constructor(private catsService: CatsService) {}

  @Post()
  async create(@Body() createCatDto: { name: string; age: number; breed: string }): Promise {
    return this.catsService.create(createCatDto);
  }

  @Get()
  async findAll(): Promise<Cat[]> {
    return this.catsService.findAll();
  }
}

The `CatsController` exposes endpoints to create a new cat and fetch all cats, relying on the service layer for business logic.

CRUD in Action

To see this in action, use your API testing tool to hit the endpoints such as `POST /cats` to create and `GET /cats` to retrieve cat entries.

Advanced: Data Transfer Objects (DTOs)

Now let’s cover some advanced topics including using DTOs for data transfer, implementing middleware for validation, using async hooks with Mongoose, and incorporating transactions.

import { IsString, IsNumber } from 'class-validator';

export class CreateCatDto {
  @IsString()
  readonly name: string;

  @IsNumber()
  readonly age: number;

  @IsString()
  readonly breed: string;
}

DTOs like `CreateCatDto` help ensure that data conforms to the specified format and types.

Conclusion

Integration of MongoDB with NestJS empowers developers to build scalable and maintainable applications. Using Mongoose within NestJS combines the robustness of TypeScript with the flexibility of MongoDB. Take the concepts here as a springboard to create complex, production-grade apps.

Next Article: How to Connect to a MySQL Database in NestJS

Previous Article: How to create a NestJS app in the current directory

Series: Nest.js Tutorials: From Basics to Advanced

Node.js

You May Also Like

  • NestJS: How to create cursor-based pagination (2 examples)
  • Cursor-Based Pagination in SequelizeJS: Practical Examples
  • MongooseJS: Cursor-Based Pagination Examples
  • Node.js: How to get location from IP address (3 approaches)
  • SequelizeJS: How to reset auto-increment ID after deleting records
  • SequelizeJS: Grouping Results by Multiple Columns
  • NestJS: Using Faker.js to populate database (for testing)
  • NodeJS: Search and download images by keyword from Unsplash API
  • NestJS: Generate N random users using Faker.js
  • Sequelize Upsert: How to insert or update a record in one query
  • NodeJS: Declaring types when using dotenv with TypeScript
  • Using ExpressJS and Multer with TypeScript
  • NodeJS: Link to static assets (JS, CSS) in Pug templates
  • NodeJS: How to use mixins in Pug templates
  • NodeJS: Displaying images and links in Pug templates
  • ExpressJS + Pug: How to use loops to render array data
  • ExpressJS: Using MORGAN to Log HTTP Requests
  • NodeJS: Using express-fileupload to simply upload files
  • ExpressJS: How to render JSON in Pug templates