MongoDB is a schema-less NoSQL database with flexible document structures, unlike SQL databases. Using MongoDB as a database brings many benefits, from easy scaling to modern database features such as transactions.

MongoDB also supports object data modeling (ODM) libraries like Mongoose. ODMs manage data relationships, validate schemas, and convert objects into data models. They make it easier to interact with a MongoDB database.

In a few steps, you will learn how to use MongoDB in a NestJS application with the dedicated NestJS mongoose package.

Step 1: Installing Dependencies

Before using Mongoose in your NestJS application, you must install it along with its native NestJS package.

Install mongoose and its native NestJS package using the npm package manager by running:

        npm install @nestjs/mongoose mongoose

Step 2: Connecting to MongoDB

When the installation finishes, navigate to your app.module.ts file. Then import MongooseModule from @nest/mongoose:

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

Next, in your imports array, call the forRoot method on MongooseModule and pass your MongoDB URI as an argument:

        imports: [MongooseModule.forRoot(process.env.MONGODB_URI)],

The forRoot method shares the database connection through all the modules in your application. It takes an optional configuration object; you can learn more about it in Mongoose's options documentation.

Step 3: Creating a Mongoose Schema

A schema is a JSON object that defines your data's structure and contents. You’ll need to create one to define how Mongoose stores your data in the MongoDB database.

In your application’s root module, create a “schemas” folder. This folder is where you will store all your schema files.

Inside your schemas folder, create a schema file and name it using the NestJS naming convention (<name>.schema.ts).

Next, add the following imports to your schema file:

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

The Prop decorator marks properties it annotates as a property in your MongoDB database.

The Schema decorator marks the class it annotates as a schema.

The SchemaFactory class contains static methods used for model creation.

The Mongoose Document represents a one-to-one mapping to documents as stored in MongoDB. You will need it as a type annotation.

Then, create a class, annotate it with the Schema decorator to mark it as a Mongoose schema, and export it:

        @Schema()
export class Demo {}

Next, create and export a union type with your class and Document:

        export type DemoDocument = Demo & Document;

Then add your desired properties to the class and annotate them with the Prop decorator. You can pass an optional configuration object to the Prop decorator and set the property as required:

        @Schema()
export class Demo {
  @Prop({ required: true })
  property_1: string;
}

The Mongoose documentation covers the configuration object in more detail.

Finally, create and export a Mongoose model via the SchemaFactory’s createForClass method and pass your class as an argument:

        export const DemoSchema = SchemaFactory.createForClass(Demo);

Your completed schema should look like this:

        import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';
 
export type DemoDocument = Demo & Document;
 
@Schema()
export class Demo {
  @Prop({ required: true })
  property_1: string;
 
  @Prop({ required: true })
  property_2: number;
 
  @Prop()
  property_3: string;
 
  @Prop({ required: true })
  property_4: boolean;
}
 
export const DemoSchema = SchemaFactory.createForClass(Demo);

Step 4: Registering the Schema

Navigate to your module’s folder and add the following imports:

        import { MongooseModule } from '@nestjs/mongoose';
import { Demo, DemoSchema } from '../schemas/demo.schema';

Next, create an “imports” array inside the @module decorator. Then, inside the array, call the forFeature method on MongooseModule.

The forFeature method takes in an array of Mongoose models. Pass in a configuration object with a name property set to the name of your schema class, and a schema property set to your created schema:

        MongooseModule.forFeature([{ name: Demo.name, schema: DemoSchema }]),

Step 5: Injecting the Mongoose Model

Next, you'll need to inject the Mongoose Model to enable the querying of your database by calling Mongoose methods on the model.

Navigate to your module’s service class, and add the following imports:

        import { Model } from 'mongoose';
import { InjectModel } from '@nestjs/mongoose';
import { Demo, DemoDocument } from '../schemas/demo.schema';

Use the Model interface as a type definition for your model, giving it access to Mongoose methods.

The InjectModel decorator injects the Mongoose model into your service class’ constructor.

Next, create a constructor inside your service class. It should take a private variable as an argument, a Model with a generic type of DemoDocument. Annotate your private variable with the InjectModel decorator and pass your schema class name as an argument:

        @Injectable()
export class DemoService {
  constructor(
    @InjectModel(Demo.name)
    private demoModel: Model<DemoDocument>,
  ) {}
}

You can query your MongoDB database by calling Mongoose methods on your private variable (demoModel).

Advantages of Using MongoDB

Besides its strong online community and ease of use, MongoDB provides high data availability and stability. It offers accelerated analytics, data aggregation, and more, making it the ideal database for your projects.