MongoDB query profiling
Capture every Mongoose query and aggregation and inspect them in the MongoDB panel.
This tutorial shows how to add the Mongoose collector to profile MongoDB queries in a NestJS application that uses @nestjs/mongoose.
Prerequisites
@eleven-labs/nest-profilerinstalled and configured@nestjs/mongooseandmongooseinstalled with a workingMongooseModuleconnection
Step 1 — Install the package
pnpm add @eleven-labs/nest-profiler-mongooseStep 2 — Register the collector
Add MongooseCollectorModule in the feature module that performs MongoDB operations:
import { MongooseModule } from '@nestjs/mongoose';
import { MongooseCollectorModule } from '@eleven-labs/nest-profiler-mongoose';
@Module({
imports: [
MongooseModule.forFeature([{ name: Review.name, schema: ReviewSchema }]),
MongooseCollectorModule.forRoot({
slowQueryThreshold: 50, // queries > 50ms highlighted (default: 100)
}),
],
})
export class ReviewsModule {}The collector injects the Connection automatically via @InjectConnection().
Step 3 — Instrument your services with spans
import { ProfilerService } from '@eleven-labs/nest-profiler';
@Injectable()
export class ReviewsService {
constructor(
@InjectModel(Review.name) private readonly model: Model<ReviewDocument>,
private readonly profiler: ProfilerService,
) {}
async findAll(): Promise<ReviewDocument[]> {
const stop = this.profiler.startSpan('mongo.reviews.findAll');
const result = await this.model.find().sort({ createdAt: -1 }).exec();
stop();
return result;
}
async getStats() {
const stop = this.profiler.startSpan('mongo.reviews.aggregate');
const result = await this.model
.aggregate([
{ $match: { status: 'approved' } },
{ $group: { _id: '$productId', avgRating: { $avg: '$rating' } } },
])
.exec();
stop();
return result;
}
}Step 4 — Test it
curl -i http://localhost:3000/reviewsCopy the X-Debug-Token header, open /_profiler/{token}, and click the MongoDB tab.
You will see:
- Each query with its operation badge (
find,aggregate, …) - Collection name
- Filter object
- Duration per query
- Slow queries highlighted in red
- Result count for find queries
How it works
The collector patches mongoose.Query.prototype.exec and mongoose.Aggregate.prototype.exec on the Mongoose instance obtained from connection.base. This captures:
- All
Model.find(),Model.findOne(),Model.findById()queries - All
Model.updateOne(),Model.deleteOne(),Model.deleteMany()mutations - All
Model.aggregate()pipelines Model.countDocuments(),Model.distinct(), and other cursor-based operations
Queries executed outside a request context (e.g., during module initialization or seeding) are silently ignored since there is no active CLS profile.
Anti-double-patch guard
If multiple modules import MongooseCollectorModule.forRoot(), the patch is applied only once — a
__profilerPatched flag prevents double-wrapping Query.prototype.exec.