MongoDB With Mongoose

NoSQL the Nest Way

MongoDB With Mongoose

For MongoDB, Nest ships `@nestjs/mongoose` — schema decorators and injectable models that feel like the TypeORM workflow.

4 min read Level 2/5 #nestjs#mongoose#mongodb
What you'll learn
  • Install @nestjs/mongoose
  • Define schemas with @Schema and @Prop
  • Inject a Model and query

Document databases are a different shape from relational ones, but Nest’s integration with Mongoose mirrors the TypeORM one closely enough that you’ll find your bearings fast.

Install and Connect

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

Use forRootAsync with ConfigService once you start caring about environment files — same pattern as TypeORM.

Define a Schema

You can write Mongoose schemas the classic way or use the decorator API from @nestjs/mongoose. The decorator version pairs well with the rest of Nest.

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, unique: true })
  email: string;

  @Prop()
  name: string;

  @Prop({ default: true })
  active: boolean;
}

export const UserSchema = SchemaFactory.createForClass(User);

timestamps: true adds the familiar createdAt / updatedAt fields. HydratedDocument<User> is the type that includes Mongoose’s _id, save(), etc.

Inject and Query

Register the schema in the feature module, then inject the model.

@Module({
  imports: [
    MongooseModule.forFeature([{ name: User.name, schema: UserSchema }]),
  ],
  providers: [UsersService],
})
export class UsersModule {}

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

  create(email: string, name: string) {
    return this.model.create({ email, name });
  }

  findActive() {
    return this.model.find({ active: true }).sort({ createdAt: -1 }).exec();
  }
}

.exec() returns a real Promise instead of Mongoose’s “thenable” Query — nicer for async/await and for testing.

When To Reach For This

Mongoose shines for flexible, document-shaped data — user profiles with varying fields, event logs, anything you’d otherwise model with a JSONB column. For straightforward relational workloads, Postgres + TypeORM or Prisma will usually serve you better.

Database Transactions →