In Mongoose, we can define middleware (also known as pre and post hooks) to trigger events before and after database operations are executed. Mongoose supports document middleware and query middleware, which can be triggered when executing operations such as save, remove, find, and update.
Defining Document Middleware
Document middleware is used for operations on individual documents. For example, execute certain actions before or after saving a document. Here is an example demonstrating how to print messages before and after saving a document:
javascriptconst mongoose = require('mongoose'); const { Schema } = mongoose; const userSchema = new Schema({ name: String, email: String }); // Pre-save middleware userSchema.pre('save', function(next) { console.log('A user document is about to be saved.'); next(); }); // Post-save middleware userSchema.post('save', function(doc) { console.log(`User ${doc.name} was saved.`); }); const User = mongoose.model('User', userSchema); const newUser = new User({ name: 'Alice', email: 'alice@example.com' }); newUser.save(); // This will trigger the above-defined pre and post save hooks
Defining Query Middleware
Query middleware is used for query operations. For example, add logic before or after executing a query. Here is an example demonstrating how to add a log after a query:
javascriptuserSchema.post('find', function(docs) { console.log(`Found ${docs.length} documents.`); }); // When calling User.find(), it will trigger the above post-find hook User.find({ name: 'Alice' }, (err, docs) => { if (err) throw err; // After the query is completed, it will also print the number of documents });
Triggering Custom Events
If you need to trigger custom events, you can use the Node.js events module to create and trigger events. Here is an extended example:
javascriptconst events = require('events'); const eventEmitter = new events.EventEmitter(); // Define an event handler const myEventHandler = () => { console.log('Custom event triggered!'); }; // Bind the event and event handler eventEmitter.on('saved', myEventHandler); // Trigger the event userSchema.post('save', function() { eventEmitter.emit('saved'); }); const anotherUser = new User({ name: 'Bob', email: 'bob@example.com' }); anotherUser.save(); // This will trigger the save hooks and also the custom event
Using this approach, we can add complex logic in Mongoose middleware, even for cross-application event communication. This makes the code more modular and reusable.