Mongoose Patterns
Quick Reference
This skill provides comprehensive Mongoose patterns for NestJS applications. Load reference files as needed:
- •entities.md - @Schema/@Prop decorators, SchemaFactory, indexes, Mongoose 9 id virtual
- •documents.md - HydratedDocument, Model types, @InjectModel pattern, DocumentArray typing
- •queries.md - find/findOne, FilterQuery, operators ($in, $or, $elemMatch), aggregation pipelines
- •embedded-schemas.md - Subdocument entities, embedding patterns, DocumentArray manipulation
- •helpers.md - Custom setters (parseNumber, parseDate), getters, virtuals, validation
Core Entity Structure
typescript
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Types } from 'mongoose';
@Schema({
timestamps: true,
versionKey: false,
toJSON: { virtuals: true },
toObject: { virtuals: true },
})
export class CarType {
@Prop({ required: true, unique: true })
name: string;
@Prop({ type: Number, unique: true, sparse: true })
rshopId?: number;
@Prop({ type: Boolean, default: true })
new?: boolean;
createdAt: Date;
updatedAt?: Date;
}
export const CarTypeSchema = SchemaFactory.createForClass(CarType);
// Add id virtual (Mongoose 9 no longer provides this by default)
CarTypeSchema.virtual('id').get(function (this: CarType & { _id: Types.ObjectId }) {
return this._id.toHexString();
});
Import Organization
Follow this strict order:
- •Framework imports (
@nestjs/mongoose,@nestjs/common) - •Third-party packages (
mongoose,date-fns) - •Generated files (
src/generated/...) - •Helper utilities (
src/database/...) - •Common modules (
src/common/...) - •Application modules (
src/modules/...) - •Relative imports (
./,../)
Document and Model Interfaces
typescript
// car-document.interface.ts
import { HydratedDocument, Types } from 'mongoose';
import { Car } from '../entities/car.entity';
import { CarEvent } from '../entities/car-event.entity';
export interface CarDocumentOverrides {
id: string;
history: Types.DocumentArray<CarEvent>;
}
export interface CarDocument
extends HydratedDocument<Car, CarDocumentOverrides> {}
// car-model.interface.ts
import { Model } from 'mongoose';
export type CarModel = Model<Car, unknown, unknown, unknown, CarDocument>;
Service with Model Injection
typescript
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Car } from './entities/car.entity';
import { CarDocument } from './interfaces/car-document.interface';
import { CarModel } from './interfaces/car-model.interface';
@Injectable()
export class CarsService {
constructor(
@InjectModel(Car.name) private carModel: CarModel,
) {}
// CRUD methods
findAll(): Promise<CarDocument[]> {
return this.carModel.find().exec();
}
findOne(id: string): Promise<CarDocument | null> {
return this.carModel.findById(id).exec();
}
create(data: CreateCarInput): Promise<CarDocument> {
const car = new this.carModel(data);
return car.save();
}
async update(car: CarDocument, data: UpdateCarInput): Promise<CarDocument> {
car.set(data);
return car.save();
}
async delete(car: CarDocument): Promise<CarDocument> {
await car.deleteOne();
return car;
}
}
When to Load Reference Files
Defining entities?
- •Schema options and @Prop variations → entities.md
- •Indexes (simple and compound) → entities.md
Setting up type safety?
- •Document and Model interfaces → documents.md
- •@InjectModel with proper typing → documents.md
Writing queries?
- •FilterQuery and operators → queries.md
- •Aggregation pipelines → queries.md
Working with nested data?
- •Subdocument schemas → embedded-schemas.md
- •DocumentArray manipulation → embedded-schemas.md
Custom data transformation?
- •Setters for parsing input → helpers.md
- •Getters for default values → helpers.md
- •Virtuals for computed fields → helpers.md