Script Valley
MongoDB: Complete Course
Mongoose and Node.js IntegrationLesson 5.3

Mongoose middleware (pre and post hooks) explained

document middleware, query middleware, pre save hook, post save hook, pre find hook, this context, next() function, error handling in hooks

Document middleware hooks

Mongoose pre and post hooks

Mongoose middleware lets you run code before (pre) or after (post) specific operations on a model. Document middleware hooks receive the document as this. Query middleware hooks receive the query object as this. Common uses: hashing passwords before save, writing audit logs after delete, and auto-filtering soft-deleted documents from all find queries.

const bcrypt = require('bcrypt')

// pre('save') — triggered before every .save() call
userSchema.pre('save', async function (next) {
  // 'this' is the document being saved
  if (!this.isModified('password')) return next() // skip if unchanged
  this.password = await bcrypt.hash(this.password, 12)
  next()
})

// post('save') — triggered after successful save
userSchema.post('save', function (doc, next) {
  console.log(`User ${doc._id} saved successfully`)
  next()
})

// Query middleware — intercepts all find-family operations
// /^find/ matches: find, findOne, findById, findOneAndUpdate, etc.
userSchema.pre(/^find/, function (next) {
  // 'this' is the Query object — chain filter conditions here
  this.find({ isDeleted: { $ne: true } })
  next()
})

Aborting an operation with an error

userSchema.pre('save', function (next) {
  if (this.age < 0) return next(new Error('Age cannot be negative'))
  next()
  // This error rejects the save() promise in the calling code
})

An important distinction: document middleware like pre('save') does not fire for operations like updateOne or updateMany called directly on the model — those bypass document middleware entirely. If you need hooks on update operations, use query middleware (pre('updateOne')) or switch to findById followed by document.save() which does trigger document hooks.

Up next

Mongoose populate: how to handle document references

Sign in to track progress