Categories
MongoDB

Using MongoDB with Mongoose — Hooks for Operations

Spread the love

To make MongoDB database manipulation easy, we can use the Mongoose NPM package to make working with MongoDB databases easier.

In this article, we’ll look at how to use Mongoose to manipulate our MongoDB database.

Save/Validate Hooks

The save method will trigger validate hooks.

This is because Mongoose calls the pre('save') hook that calls validate .

The pre('validate') and post('validate') hooks are called before any pre('save') hooks.

For example, we can write:

async function run() {  
  const { createConnection, Schema } = require('mongoose');  
  const connection = createConnection('mongodb://localhost:27017/test');  
  const schema = new Schema({ name: String });  
  schema.pre('validate', () => {  
    console.log('1');  
  });  
  schema.post('validate', () => {  
    console.log('2');  
  });  
  schema.pre('save', () => {  
    console.log('3');  
  });  
  schema.post('save', () => {  
    console.log('4');  
  });  
  const User = connection.model('User', schema);  
  new User({ name: 'test' }).save();  
}  
run();

to add the schema hooks.

Then they’ll be called one by one in the same order that they’re listed.

Query Middleware

Pre and post save hooks aren’t run when update methods are run.

For example, if we have:

async function run() {  
  const { createConnection, Schema } = require('mongoose');  
  const connection = createConnection('mongodb://localhost:27017/test');  
  const schema = new Schema({ name: String });  
  schema.pre('updateOne', { document: true, query: false }, function() {  
    console.log('Updating');  
  });  
  const User = connection.model('User', schema);  
  const doc = new User();  
  await doc.updateOne({ $set: { name: 'test' } });  
  await User.updateOne({}, { $set: { name: 'test' } });  
}  
run();

Then when we have query set to false or didn’t add the query property, then the updateOne pre hook won’t run when we run updateOne .

Aggregation Hooks

We can add aggregation hooks.

For example, we can write:

async function run() {  
  const { createConnection, Schema } = require('mongoose');  
  const connection = createConnection('mongodb://localhost:27017/test');  
  const schema = new Schema({  
    name: {  
      type: String,  
      unique: true  
    }  
  });  
  schema.pre('aggregate', function() {  
    this.pipeline().unshift({ $match: { isDeleted: { $ne: true } } });  
  });  
  const User = connection.model('User', schema);  
}  
run();

We listen to the aggregate event.

Error Hooks

We can get errors from hooks.

For example, we can write:

async function run() {  
  const { createConnection, Schema } = require('mongoose');  
  const connection = createConnection('mongodb://localhost:27017/test');  
  const schema = new Schema({  
    name: {  
      type: String,  
      unique: true  
    }  
  });  
  schema.post('update', function (error, res, next) {  
    if (error.name === 'MongoError' && error.code === 11000) {  
      next(new Error('There was a duplicate key error'));  
    } else {  
      next();  
    }  
  });  
  const User = connection.model('User', schema);  
}  
run();

We listen to the update event and get the error from the error parameter.

We can get the name and code to get information about the error.

Synchronous Hooks

Some hooks are always synchronous.

init hooks are always synchronous because the init function is synchronous.

For example, if we have:

async function run() {  
  const { createConnection, Schema } = require('mongoose');  
  const connection = createConnection('mongodb://localhost:27017/test');  
  const schema = new Schema({  
    name: String  
  });  
  schema.pre('init', obj => {  
    console.log(obj);  
  });  
  const User = connection.model('User', schema);  
}  
run();

We added the pre init hook with a callback.

Conclusion

We can add middleware for various events that are emitted when we manipulate data with Mongoose.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *