NestJS — Enterprise Node.js

MongoDB with Mongoose

17 min Lesson 25 of 30

MongoDB with Mongoose

Not every application fits a relational database. MongoDB is a document database that stores flexible, JSON-like documents — a great fit for content, catalogs, and rapidly-evolving schemas. NestJS integrates it through Mongoose, the most popular MongoDB library for Node.js, via the @nestjs/mongoose package.

SQL vs document thinking

In MongoDB you store documents in collections (rather than rows in tables). Related data is often embedded inside a document instead of split across tables and joined — which can make reads faster but changes how you model data.

Connecting

// npm install @nestjs/mongoose mongoose import { MongooseModule } from '@nestjs/mongoose'; @Module({ imports: [ MongooseModule.forRoot('mongodb://localhost/app'), ], }) export class AppModule {}

Defining a schema

With @nestjs/mongoose you define schemas as classes using the @Schema() and @Prop() decorators — familiar after TypeORM entities:

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; import { HydratedDocument } from 'mongoose'; export type UserDocument = HydratedDocument<User>; @Schema({ timestamps: true }) export class User { @Prop({ required: true }) name: string; @Prop({ required: true, unique: true }) email: string; @Prop({ default: true }) isActive: boolean; } export const UserSchema = SchemaFactory.createForClass(User);

Registering and injecting the model

Register the schema with forFeature(), then inject the model with @InjectModel():

// users.module.ts MongooseModule.forFeature([{ name: User.name, schema: UserSchema }]); // users.service.ts import { InjectModel } from '@nestjs/mongoose'; import { Model } from 'mongoose'; @Injectable() export class UsersService { constructor(@InjectModel(User.name) private userModel: Model<UserDocument>) {} async create(dto: CreateUserDto) { return new this.userModel(dto).save(); } findAll() { return this.userModel.find().exec(); } }
The model is your gateway. A Mongoose Model provides find, findById, create, updateOne, deleteOne, and more — the document-database equivalent of a repository.

Schema design trade-offs

  • Embedding — store related data inside the parent document. Fast reads, but documents can grow large and duplicated data is harder to update.
  • Referencing — store an id and look it up separately (like a foreign key). Normalised, but needs an extra query (populate()).
Schema-less does not mean think-less. MongoDB's flexibility tempts teams to skip data modelling. Inconsistent document shapes become a maintenance nightmare. Use schemas (as above) and model your access patterns deliberately.
Choose the database for the data, not the hype. Relational stores excel at structured, highly-related data with strong consistency; document stores excel at flexible, denormalised, read-heavy data. NestJS supports both equally well behind the same module/service patterns.

Summary

MongoDB stores flexible documents in collections, integrated into NestJS via Mongoose and @nestjs/mongoose. Define schemas with @Schema()/@Prop(), register them with forFeature(), and inject a typed Model with @InjectModel() to query and persist. Model embedding vs referencing deliberately. This completes Phase 5 — you can now persist data with relational and document databases. Next: authentication and authorization.