Mongoose middleware lets you run code before or after certain actions on your data. It helps automate tasks like validation, logging, or modifying data.
You want to check or change data before saving it to the database.
You need to log information every time a document is deleted.
You want to update related data automatically after a document is updated.
You want to run cleanup tasks before removing a document.
You want to validate or modify data before running queries.
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
Sets a creation date before saving a user.
Express
userSchema.pre('save', function(next) {
this.createdAt = new Date();
next();
});
Logs a message after a user is removed.
Express
userSchema.post('remove', function(doc, next) {
console.log(`User ${doc._id} was removed.`);
next();
});
Updates the 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);
OutputSuccess
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/5)
1. What is the main purpose of pre middleware in Mongoose?
easy
A. To connect to the MongoDB database
B. To run code after a database operation completes
C. To define the schema structure
D. To run code before a database operation like save or remove
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 D
Quick 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
A. schema.on('save', function(next) { /* code */ next(); });
B. schema.pre('save', function(next) { /* code */ next(); });
C. schema.before('save', function() { /* code */ });
D. schema.post('save', function(next) { /* code */ next(); });
Solution
Step 1: Recall Mongoose middleware method names
Mongoose uses pre and post methods for middleware, not before or on.
Step 2: Check syntax for pre-save hook
The correct syntax is schema.pre('save', function(next) { ... next(); }); to run code before saving.