ScanSkill
Sign up for daily dose of tech articles at your inbox.
Loading

Detailed Way To Implement MongoDB In NestJS

Detailed Way To Implement MongoDB In NestJS
Detailed Way To Implement MongoDB In NestJS

In this article, we are going to learn the detailed way to implement MongoDB in NestJS. Also after the setup, we will also look into performing CRUD operations with MongoDB through NestJS.

Introduction

NestJS is a framework for building scalable Node.js server-side applications. It uses the Express HTTP Server framework under the hood which is a framework based on Node.js. Nest has full TypeScript support and uses it primarily, but users can also use JavaScript. It combines the support for Object-Oriented Programming (OOP), Functional Programming (FP), and Functional Reactive Programming (FRP). NestJS gives developers the freedom to use third-party modules made for Node. Node.js. Nest provides out-of-the-box application architecture based on the Model View Controller (MVC) architecture making the written application highly testable, scalable, easily maintainable, and loosely coupled. It is heavily inspired by Angular making it easier for angular developers to get up and running NestJS faster.

MongoDB is an open-source non-relational, document-based database. It is based on storing data in an Object-based format. MongoDB runs on all platforms like Linux, Windows, and UNIX. MongoDB is one of the best No-SQL databases used for applications, ranging from web-based applications to server-side applications.

Now we are going to look at how to work with MongoDB in NestJS.

Setting up the Application – Implement MongoDB in NestJS

In this section firstly, we will initialize the nest application and add and implement the sequelize package to facilitate the MongoDB database connection.

Initializing a NestJS application

Let’s set up a Nest application by using the nest CLI.

## initializing a nest application
$ nest new nest-mongodb

## open the application with your favorite code editor
$ code nest-mongodb
initializing a NestJS application - Implement MongoDB In NestJS
initializing a NestJS application
After installation open it with your favorite code editor
After installation open it with your favorite code editor
Initialized project - Implement MongoDB In NestJS
Initialized project

Now that the nest application is initialized, we will install some dependencies that are needed for integrating MongoDB.

Adding and implementing the mongoose package

Finally, We are going to interact with MongoDB using the mongoose package which is a modern TypeScript and an ORM library that creates a connection between MongoDB and the Express-based web application frameworks. Therefore, install the mongoose package to work with and implement MongoDB in NestJS.

$  npm install --save @nestjs/mongoose mongoose
Mongoose package installation - Implement MongoDB In NestJS
Mongoose package installation

Now that the dependencies are added we need to initialize mongoose to create a connection with MongoDB. We initialize mongoose in the main module of the application, that being app.module.ts. We add the code for connecting to the MongoDB database in the imports key of the @Module() decorator.

//# app.module.ts

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

@Module({
  imports: [
    MongooseModule.forRoot(
      'mongodb+srv://user:password@example.mongodb.net/scanskill?retryWrites=true&w=majority',
    )],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

In the above code, the MongooseModule.forRoot() takes MongoDB connection URL is appended with username, password, and database name. Now let’s run the application and test our connection with the MongoDB database. These secret URLs must be kept as environment variables,to learn about interacting with environment variables look at the article How To Work With Environment Variables in Node.js.

$ npm run start:dev
Connection success to the MongoDB
Connection success to the MongoDB

If mongoose dependencies are initialized and mongoose core module dependencies are initialized, it means that the connection to the MongoDB database was a success.

Now that the connection to the database was a success. We will perform CRUD operations on MongoDB using the mongoose package.

CRUD operations

Now that we have initialized the application and created a connection with the MongoDB database, the next step is performing CRUD operations with it. We are going to interact with the user collection. For that to be possible we need to make a schema of the user collection. The reason we need to make a schema is that the mongoose package requires it for interacting with the collections present inside the MongoDB database.

Creating Schema

We are going to create a schema named user which has elements like name, email, password, createdAt, and updatedAt.

For that let’s first create a user module that houses all the user-related operations.

$ nest g module user --no-spec
creating user module - Implement MongoDB In NestJS
creating user module
User module file created inside the user folder
User module file created inside the user folder

Now, that the user module is created inside the user folder, we create a folder called schemas and make a file named user.schema.ts, that contains the user schema.

File and folder for user schema created - Implement MongoDB In NestJS
File and folder for user schema created

Now, let’s create the user schema

//# user.schema.ts

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

export type userDocument = User & Document;

@Schema({ strict: false, versionKey: false })
export class User {
  @Prop()
  name?: string;

  @Prop({ required: true, unique: true })
  email: string;

  @Prop({ required: true })
  password: string;

  @Prop({ required: true })
  createdAt: Date;

  @Prop({ required: true })
  updatedAt: Date;
}

export const UserSchema = SchemaFactory.createForClass(User);

We create a class that has variables that can be represented as string, Date, number, and different other types. the @Schema() decorator tells that it is a mongoose schema. the @Prop() takes different keys like, is the value is required then the required: true is used. If the element needs to be unique then the unique: true is used.

If the value needs to be optional then ?: needs to be used instead of : as seen in the case of name and email respectively. where name is optional name ?: string is used and in the case where email is required email: string is used.

For this schema to be usable we need to import in the user.module.ts file, inside the imports array of @Module() decorator.

//# user.module.ts

import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { User } from './schemas/user.schema';

@Module({
  imports: [MongooseModule.forFeature([{ name: User.name, schema: User }])],
})
export class UserModule {}

Now that the schema is created and imported into the user module. We will now create user controller and service.

$ nest g service user --no-spec
$ nest g controller user --no-spec
Creating user controller and service - Implement MongoDB In NestJS
Creating user controller and service
created user service and controller - Implement MongoDB In NestJS
created user service and controller

Now, the controller, service, and schema are present in the file. So, let’s move on to the main part which is performing crud operations.

Create operation

We are going to create a method called insertOne() inside user service and controller, which creates users.

//# user.service.ts

import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { User, userDocument } from './schemas/user.schema';

@Injectable()
export class UserService {
  constructor(
    @InjectModel(User.name) private readonly model: Model<userDocument>,
  ) {}

  async insertOne(data): Promise<User> {
    return await new this.model({
      ...data,
      createdAt: new Date(),
      updatedAt: new Date(),
    }).save();
  }
}
//# user.controller.ts

import { Body, Controller, Post} from '@nestjs/common';
import { UserService } from './user.service';

@Controller('user')
export class UserController {
  constructor(private readonly userService: UserService) {}

  @Post()
  async insertOne(@Body() body) {
    return await this.userService.insertOne(body);
  }
}

Now, let’s create an HTTP POST request at /user route

HTTP POST request to /user
HTTP POST request to /user
Success response stating that the user has been created - Implement MongoDB In NestJS
Success response stating that the user has been created
User data in the MongoDB database
User data in the MongoDB database

We see that the data has been successfully present on the database.

Read operation

For the read let’s create findAll() method which finds all the data present inside the user collection.

//# user.service.ts

import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { User, userDocument } from './schemas/user.schema';

@Injectable()
export class UserService {
  constructor(
    @InjectModel(User.name) private readonly model: Model<userDocument>,
  ) {}

  async findAll(): Promise<User[]> {
    return await this.model.find().exec();
  }
}
//# user.controller.ts

import { Body, Controller, Get } from '@nestjs/common';
import { UserService } from './user.service';

@Controller('user')
export class UserController {
  constructor(private readonly userService: UserService) {}

  @Get()
  async findAll() {
    return await this.userService.findAll();
  }

}

Now let’s create an HTTP GET request on the /user route

Creating HTTP GET request on the /user route
Creating HTTP GET request on the /user route
All the data present inside the user collection - Implement MongoDB In NestJS
All the data present inside the user collection

We see that all the data present inside the user collection were in response.

Update operation

For update let’s create updateOne() method inside the user controller and service.

//# user.service.ts

import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { User, userDocument } from './schemas/user.schema';

@Injectable()
export class UserService {
  constructor(
    @InjectModel(User.name) private readonly model: Model<userDocument>,
  ) {}

  async updateOne(id: string, data): Promise<User> {
    const updatedAt = new Date();
    const oldPayload = await this.model.findByIdAndUpdate(id, {
      ...data,
      updatedAt,
    });
    const result: any = {
      _id: oldPayload._id,
      email: data.email || oldPayload.email,
      password: data.password || oldPayload.password,
      createdAt: oldPayload.createdAt,
      updatedAt: updatedAt,
    };
    return result;
  }
}
//# user.controller.ts

import { Body, Controller, Param, Put } from '@nestjs/common';
import { UserService } from './user.service';

@Controller('user')
export class UserController {
  constructor(private readonly userService: UserService) {}

  @Put('/:id')
  async updateOne(@Param('id') id: string, @Body() body) {
    return await this.userService.updateOne(id, body);
  }

}

Now, let’s send an HTTP PUT request with the user id of /user/:id.

HTTP PUT request on /user/:id route
HTTP PUT request on /user/:id route
update payload
update payload

Before update

User data before update - Implement MongoDB In NestJS
User data before update

After update

User data after update
User data after update

So, we can see that the data that was sent has been updated in the user collection.

Delete operation

Now let’s create deleteOne() method which deletes the user with matched id.

//# user.service.ts

import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { User, userDocument } from './schemas/user.schema';

@Injectable()
export class UserService {
  constructor(
    @InjectModel(User.name) private readonly model: Model<userDocument>,
  ) {}

  async deleteOne(id: string): Promise<User> {
    return await this.model.findByIdAndDelete(id);
  }

}
//# user.controller.ts

import { Controller, Delete, Param } from '@nestjs/common';
import { UserService } from './user.service';

@Controller('user')
export class UserController {
  constructor(private readonly userService: UserService) {}

  @Delete('/:id')
  async deleteOne(@Param('id') id: string) {
    return await this.userService.deleteOne(id);
  }

}

Now, let’s send an HTTP DELETE request at /user/:id route.

HTTP DELETE request on /user/:id route
HTTP DELETE request on /user/:idroute
Data present in the database before deletion - Implement MongoDB In NestJS
Data present in the database before deletion
Data in the database after deletion - Implement MongoDB In NestJS
Data in the database after deletion

We can see that the single user present in the user collection has been deleted.

So, this concludes performing CRUD operation in MongoDB with NestJS.

Conclusion

In this article saw and learned how to work and implement MongoDB with NestJs along with performing CRUD operations on it. For learning backend development along with NestJs visit JavaScript Backend Development Course For Beginners.

Sign up for daily dose of tech articles at your inbox.
Loading