Mongoose middleware lets you run code before or after certain actions on your data. It helps automate tasks like validation, logging, or modifying data.
Mongoose middleware (pre/post hooks) in Express
Start learning this pattern below
Jump into concepts and practice - no test required
or
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Introduction
Syntax
Express
schema.pre('action', function(next) { // code to run before action next(); }); schema.post('action', function(doc, next) { // code to run after action next(); });
pre runs before the action, post runs after.
Always call next() to continue the process.
Examples
Express
userSchema.pre('save', function(next) {
this.createdAt = new Date();
next();
});Express
userSchema.post('remove', function(doc, next) { console.log(`User ${doc._id} was removed.`); next(); });
updatedAt field before updating a user.Express
userSchema.pre('findOneAndUpdate', function(next) { this.set({ updatedAt: new Date() }); next(); });
Sample Program
This example shows three middleware hooks: one sets createdAt before saving, one sets updatedAt before updating, and one logs a message after removing a user.
Express
import mongoose from 'mongoose'; const userSchema = new mongoose.Schema({ name: String, createdAt: Date, updatedAt: Date }); // Pre-save hook to set createdAt userSchema.pre('save', function(next) { if (!this.createdAt) { this.createdAt = new Date(); } next(); }); // Pre-update hook to set updatedAt userSchema.pre('findOneAndUpdate', function(next) { this.set({ updatedAt: new Date() }); next(); }); // Post-remove hook to log removal userSchema.post('remove', function(doc) { console.log(`User ${doc._id} removed.`); }); const User = mongoose.model('User', userSchema); async function run() { await mongoose.connect('mongodb://localhost:27017/testdb'); // Create and save user const user = new User({ name: 'Alice' }); await user.save(); // Update user await User.findOneAndUpdate({ _id: user._id }, { name: 'Alice Updated' }); // Remove user await user.remove(); await mongoose.disconnect(); } run().catch(console.error);
Important Notes
Middleware functions must call next() to continue the operation.
Use pre hooks to modify data before actions, and post hooks for side effects like logging.
For query middleware like findOneAndUpdate, use this.set() to change update data.
Summary
Mongoose middleware runs code before or after database actions.
Use pre hooks to prepare or validate data.
Use post hooks to perform tasks after actions, like logging.
Practice
1. What is the main purpose of
pre middleware in Mongoose?easy
Solution
Step 1: Understand middleware timing
Pre middleware runs before a database action, allowing preparation or validation.Step 2: Differentiate pre and post hooks
Post middleware runs after the action, so pre is for before actions.Final Answer:
To run code before a database operation like save or remove -> Option DQuick Check:
Pre middleware = before action [OK]
Hint: Pre means before the action starts [OK]
Common Mistakes:
- Confusing pre with post middleware
- Thinking pre defines schema structure
- Assuming pre connects to database
2. Which of the following is the correct syntax to add a pre-save hook in Mongoose?
easy
Solution
Step 1: Recall Mongoose middleware method names
Mongoose usespreandpostmethods for middleware, notbeforeoron.Step 2: Check syntax for pre-save hook
The correct syntax isschema.pre('save', function(next) { ... next(); });to run code before saving.Final Answer:
schema.pre('save', function(next) { /* code */ next(); }); -> Option BQuick Check:
Use schema.pre for pre hooks [OK]
Hint: Use schema.pre('event', fn) for pre hooks [OK]
Common Mistakes:
- Using schema.post instead of schema.pre for pre hooks
- Using non-existent methods like before or on
- Forgetting to call next() in middleware
3. Given this Mongoose pre-save middleware, what will be the value of
doc.updatedAt after saving?schema.pre('save', function(next) {
this.updatedAt = new Date();
next();
});medium
Solution
Step 1: Understand pre-save middleware effect
The middleware setsthis.updatedAtto the current date before saving.Step 2: Confirm middleware runs before save
Since it runs before save, the document'supdatedAtwill be updated to the current time.Final Answer:
The current date and time when save is called -> Option CQuick Check:
Pre-save sets updatedAt = now [OK]
Hint: Pre-save runs before saving, so updatedAt is current time [OK]
Common Mistakes:
- Assuming updatedAt is undefined without schema field
- Confusing createdAt with updatedAt
- Thinking next() is missing causing error
4. What is wrong with this Mongoose middleware code?
schema.pre('remove', (next) => {
console.log('Removing', this._id);
next();
});medium
Solution
Step 1: Check function type in middleware
Mongoose middleware requires normal functions to bindthisto the document.Step 2: Identify arrow function issue
Arrow functions do not bindthis, sothiswill be undefined inside the middleware.Final Answer:
Arrow function does not bind 'this', so 'this' is undefined inside middleware -> Option AQuick Check:
Use normal functions for middleware to access this [OK]
Hint: Use function() not arrow to access this in middleware [OK]
Common Mistakes:
- Using arrow functions in middleware
- Forgetting to call next() in async middleware
- Thinking remove event is unsupported
5. You want to log a message after a document is saved and also update a cache. Which Mongoose middleware setup is correct?
hard
Solution
Step 1: Identify when to run logging and cache update
Logging and cache update should happen after saving, so use post middleware.Step 2: Choose correct function syntax
Post middleware receives the saved document as first argument; use normal function to accessthisif needed.Final Answer:
Use schema.post('save', function(doc) { console.log('Saved:', this._id); updateCache(this); }); -> Option AQuick Check:
Post-save + normal function for logging/cache [OK]
Hint: Use post-save with normal function for after-save tasks [OK]
Common Mistakes:
- Using pre instead of post for after-save tasks
- Using arrow functions losing this context
- Not passing doc argument in post middleware
