Validating schemas with Mongoose

For the past couple of weeks I’ve been working on a NodeJS application. One of the most important tasks was to validate the data being written to the Mongo database. Thankfully Mongoose was there to help.

The great thing about Mongoose is that it lets you define schemas and validation in quite a nice way. A basic example would look like:

1
2
3
4
5
6
7
8
9
10
var mySchema = new Schema({
  title: {
    type: String,
    required: true
  },
  date: {
    type: Date,
    default: Date.now
  }
});

And there’s more. It also lets you add custom validation:

1
2
3
4
5
var customValidator = function (value) {
  if (value.length > 10) {
    return false;
  }
};

And you would use it like this:

1
2
3
4
5
6
7
var mySchema = new Schema({
  title: {
    type: String,
    required: true,
    validate: customValidator
  }
});

There is a caveat though. When writing a new document to the database the validation worked as expected, however when I updated an existing document I discovered that the validation wasn’t working.

After some digging I discovered that validation is bypassed when you call update on a model. This is because update is essentially a pass-through to the native Mongo driver, and as Mongoose validation is middleware, it doesn’t get executed during an update.

The solution is to find the document you wish to update, apply the changes and then call save on it. A simplified version of the code looks like this:

1
2
3
4
5
6
7
8
Model.findOne({
  _id: req.params.id
}, function (error, model) {
  _.assign(model, req.body);
  application.save(function () {
    res.json(model);
  });
});

Note: In this example I’ve used the assign method from lodash to merge the changes into my model. This isn’t native to Node, Express or Mongoose, but incredibly useful for this purpose.

All in all I think Mongoose is a great tool for interacting with Mongo from a Node/Express app. I still find it puzzling as to why update bypasses validation, as it’s the simplest way to update documents, but without working validation it’s useless. That aside, I highly recommend giving it a try.