Published on

How to Create Mongoose Plugin

Authors

Mongoose is one of the most popular ORMs for MongoDB focused on improving the Developer Experience (DX) when working with MongoDB.

It abstracts the complex logic behind interacting with a database.

By default, MongoDB is schema-less. However, working with schema-less data might not be a good choice for most of the use cases.

That's where Mongoose comes in. It follows schema-based approach in which we define the schema of the model (think of like columns that we define while creating table columns in SQL)

And with that schema, we validate things before/after actually interacting with the database.

In the schema, we can do a lot of things like validation, configuring the index, default value, etc. We can also add custom logic in the schema.

And plugins are used to share your custom logic across the schemas (And we can share it with the community 😊)

Let's get started:

Plugin Outline

// 
function MyCustomPlugin(schema, options) {
  // your custom logic here
}
ParameterDescription
schemaThe current schema
optionsCustom options for your plugin

Note: Prefer using regular function since mongoose plugin might need to access schema instance using this function. "this" won't work as expected in arrow function

Creating a Plugin - Virtual ID

By default, MongoDB uses _id for the record id. Let's say we want to use id instead of that.

In that case, we can use virtuals

Instead of doing that every single time, we're going to create a plugin and use it across

// duplicate-id.js
export function duplicateIdPlugin(schema, options) {
    // Duplicate the ID field.
    schema.virtual("id").get(function () {
        return this._id.toHexString();
    });

    // Ensure virtual fields are serialised.
    schema.set("toJSON", {
        virtuals: true,
    });

    // Ensure virtual fields are serialised.
    schema.set("toObject", {
        virtuals: true,
    });
};

export default duplicateIdPlugin;

And now we can just import that plugin in the schema and register it as a plugin.

// exampleSchema.js
import mongoose from "mongoose";
import duplicateIdPlugin from './duplicate-id'

const { Schema } = mongoose;
const exampleSchema = new Schema({})

/**
 * 1. If you have multiple plugins then use the plugin() again to register like exampleSchema.plugin(anotherPlugin)
 * 2. Apply plugins "Before" assigning model like mongoose.model("Example", exampleSchema);
 */
// 

exampleSchema.plugin(duplicateIdPlugin) 

mongoose.model("Example", exampleSchema);

Registering Global Plugin

Prefer registering the plugin globally?

Just use mongoose.plugin() function instead.

import mongoose from "mongoose";
import duplicateIdPlugin from './duplicate-id'
mongoose.plugin(duplicateIdPlugin)

Reference

Happy custom plugins!