How to Use Mongoose Middleware and Hooks?


How to Use Mongoose Middleware and Hooks?

Mongoose is the most preferred ODM (Object Data Modeling) library in Node.js based MongoDB applications. Mongoose middleware and hooks allow you to automatically run a custom code block right before or after database operations. This feature is very important for managing your business logic in a modular and secure way. In this article, we cover in detail how to use Mongoose middleware and hooks, what types there are, and how they are applied in real-world scenarios.

What is Mongoose Middleware? What Are Its Types?

Mongoose middleware allows you to intervene in a document during database operations. There are especially two types: pre and post:

  • Pre Middleware: Kicks in just before the main operation occurs.
  • Post Middleware: Runs after the main operation is completed.

These can be applied at different levels such as document middleware (e.g. save, validate), query middleware (e.g. find, findOne), model middleware (e.g. insertMany), and aggregate middleware. Each type of middleware and hook is suitable for functions such as data manipulation, logging, and error handling before or after the operation.

How to Add Mongoose Middleware and Hooks?

Using Pre (Before) Middleware

If we want to perform an operation before saving a document, we can define a pre middleware. For example, password hashing is a typical example:


const mongoose = require('mongoose');
const bcrypt = require('bcrypt');

const userSchema = new mongoose.Schema({
  username: String,
  password: String
});

userSchema.pre('save', async function(next) {
  if (!this.isModified('password')) return next();
  this.password = await bcrypt.hash(this.password, 10);
  next();
});

Using Post (After) Middleware

If you want to keep logs or send notifications after some operations, you can use post middleware:


userSchema.post('save', function(doc, next) {
  console.log('User saved:', doc.username);
  next();
});

Example of Query and Model Middleware

In the code below, you can ensure that the password field is excluded by default when querying users:


userSchema.pre('find', function() {
  this.select('-password');
});

Tips for Mongoose Middleware and Hooks

  • Thanks to asynchronous middleware support, you can easily perform awaited operations using async/await.
  • Apart from pre/post that can be used schema-wide, be sure to define more isolated middleware for specific operations.
  • Avoid unnecessary middleware for performance reasons. Especially in large data operations, middlewares can slow things down.

Conclusion

The answer to how to use Mongoose middleware and hooks is very critical in terms of maintaining data integrity, abstracting business logic, and simplifying error handling in your projects. To develop high-quality Node.js applications, you must learn to use the Mongoose middleware structure effectively.