Mongoose plugin runs for every new Schema

If you want to consistently apply changes to every Schema in Mongoose, it’s simple. Below is an example.

var mongoose = require('mongoose');

var checkForHexRegExp = new RegExp("^[0-9a-fA-F]{24}$");

mongoose.plugin(function(schema, opts) {
    schema.statics.isObjectId = function(id) {
       if(id) {
           return checkForHexRegExp.test(id);
       }
       return false;
    };
});

var AnimalSchema = mongoose.Schema({
    name: String
});

var Animal = mongoose.model("Animal", AnimalSchema);

if(Animal.isObjectId("521b4891039857e07aae695a")) {
    var animal = new Animal();
    // something more interesting here ...
}

The code above uses the plugin function on the global mongoose object to add a new plugin. When you add a plugin using that technique, it runs for every schema that is constructed.

So, in this case, I’ve added a static function to every Schema called isObjectId which uses a simple regular expression (liberally borrowed straight from the bson ObjectId source code) to test whether a string looks like a valid ObjectId (in fact, a 24 character HEX string).

Now, as new models are created (mongoose.model), the Schema is first passed to any defined plugins. The plugin adds the new function isObjectId. As you can see, the new Model has a static method called isObjectId.

The plugin will not affect any Schemas/Models that were defined before the plugin was added.

Using this technique, you could add standardized fields, indexes, etc. without repeating the same code to all Schemas. Of course, you can also use the plugin method defined on a Schema to selectively add functionality.

var isObjectIdPlugin = function(schema, opts) {
    schema.statics.isObjectId = function(id) {
        if(id) {
            return checkForHexRegExp.test(id);
        }
        return false;
    };
};


var AnimalSchema = mongoose.Schema({
    name: String
});

AnimalSchema.plugin(isObjectIdPlugin);

var Animal = mongoose.model("Animal", AnimalSchema);

if(Animal.isObjectId("521b4891039857e07aae695a")) {
    var animal = new Animal();
    // something more interesting here ...
}

Above, the code applies the plugin to only the AnimalSchema using the plugin method.

Of course, adding the same method statically may not be very useful – instead it probably belongs somewhere in a utility class (and really it’s too bad it’s not just exposed directly by the BSON ObjectId class).