Why Mongoose doesn't validate on update?
As of Mongoose 4.0 you can run validators on update()
and findOneAndUpdate()
using the new flag runValidators: true
.
Mongoose 4.0 introduces an option to run validators on
update()
andfindOneAndUpdate()
calls. Turning this option on will run validators for all fields that yourupdate()
call tries to$set
or$unset
.
For example, given OP's Schema:
const ClientSchema = new Schema({
name: {type: String, required: true, trim: true}
});
const Client = mongoose.model('Client', ClientSchema);
Passing the flag on each update
You can use the new flag like this:
const id = req.params.id;
const client = req.body;
Client.update({_id: id}, client, { runValidators: true }, function(err) {
....
});
Using the flag on a pre
hook
If you don't want to set the flag every time you update something, you can set a pre
hook for findOneAndUpdate()
:
// Pre hook for `findOneAndUpdate`
ClientSchema.pre('findOneAndUpdate', function(next) {
this.options.runValidators = true;
next();
});
Then you can update()
using the validators without passing the runValidators
flag every time.
You're not doing anything wrong, validation
is implemented as internal middleware within Mongoose and middleware doesn't get executed during an update
as that's basically a pass-through to the native driver.
If you want your client update validated you'll need to find
the object to update, apply the new property values to it (see underscore's extend
method), and then call save
on it.
Mongoose 4.0 Update
As noted in the comments and victorkohl's answer, Mongoose now support the validation of the fields of $set
and $unset
operators when you include the runValidators: true
option in the update
call.
MongoDB does not run validation on updates by default.
in order to make validation works by default when an update happens, just before connecting to MongoDB you can set global setting only ones like that:
mongoose.set('runValidators', true); // here is your global setting
mongoose.connect(config.database, { useNewUrlParser: true });
mongoose.connection.once('open', () => {
console.log('Connection has been made, start making fireworks...');
}).on('error', function (error) {
console.log('Connection error:', error);
});
So any built-in or custom validation will run on any update as well