Currently I am using pre('save')
to do validation:
UserSchema.pre('save', true, function(next, done) {
var self = this //in case inside a callback
var msg = helper.validation.user.username(self.username)
if (msg) {
self.invalidate('username', msg)
done(helper.getValidationError(msg))
}
else
done()
next()
})
The helper module has a function that accepts an input and returns error message.
exports.user = {
username: function(input) {
if (!input)
return 'username is required'
var min = 3
var max = 10
if (input.length < min)
return 'username min of length is ' + min
if (input.length > max)
return 'username max of length is ' + max
return null
}
}
There is another api validate
to do similar things. What's the difference between them and which one should I use in what cases?
Mongoose gives us a set of useful built-in validation rules such: Required validator checks if a property is not empty. Numbers have min and max validators. Strings have enum , match , minlength , and maxlength validators.
The save() function triggers validate() hooks, because mongoose has a built-in pre('save') hook that calls validate() . This means that all pre('validate') and post('validate') hooks get called before any pre('save') hooks.
Validation is defined in the SchemaType. Validation is middleware. Mongoose registers validation as a pre('save') hook on every schema by default. You can disable automatic validation before save by setting the validateBeforeSave option. You can manually run validation using doc.
mongoose-unique-validator is a plugin which adds pre-save validation for unique fields within a Mongoose schema. This makes error handling much easier, since you will get a Mongoose validation error when you attempt to violate a unique constraint, rather than an E11000 error from MongoDB.
Update:
The validation is performed before the user defined hooks. You can follow this github post, where the contributor states,
not implementing this. validating first gives us a chance to stop before continuing into user defined hooks which may include async updates to other collections.
if we need validation to run again after we make a change from inside a hook we can always manually run
this.validate(next)
.
Outdated:
Yeah, there is a small difference i know.
Pre hooks are executed before validations.
There is a closed issue on github asking for validation before pre hooks, https://github.com/Automattic/mongoose/issues/400.
Say you have two fields, foo and fooSort, both are required. fooSort is a lowercased or otherwise transformed version of foo to be used in sorting. Since fooSort can be automatically generated, it makes sense to do so in a pre-save hook. But since validation runs first, it will fail before the pre-save hook runs and has a chance to fill in the fooSort value. It isn't a question of being able to run validation again manually.
Again, if you want to validate something and then need the hook for post validate:
UserSchema.post('validate', function(next){
console.log("post validate called");
next();
});
you can use both as long as you get inputs to save in db directly without altering anything (only validation).
If you are altering anything you have to use pre save hook.
The above answer is incorrect. If you go to: https://github.com/Automattic/mongoose/issues/400 and read the responses to the topic from the mongoose contributor you'll see that he notes they are run before on purpose.
The topic is named: Validation should run after all other pre-save hooks
Mongoose contributor aheckmann states that:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With