First of all, this doesn't help.
Let's say, we have a User model:
const schema = new mongoose.Schema({
active: { type: Boolean },
avatar: { type: String }
});
const User = mongoose.model('User', schema);
When we update it (set an avatar):
// This should pass validation
User.update({ _id: id }, { $set: { avatar: 'user1.png' } });
We want to validate it based on current (or changed) active
attribute value.
active
is false
active
is true
const schema = new mongoose.Schema({
active: { type: Boolean },
avatar: { type: String, validate: [validateAvatar, 'User is not active'] }
});
function validateAvatar (value) {
console.log(value); // user.avatar
console.log(this.active); // undefined
}
So this will not work as we don't have an access to active
field.
schema.pre('validate', function (next) {
// this will never be called
});
This hook doesn't work with update
method.
schema.pre('update', function (next) {
console.log(this.active); // undefined
});
This will not work for us as it doesn't have an access to model fields.
schema.post('update', function (next) {
console.log(this.active); // false
});
This one works, but in terms of validation is not quite good choice, as the function is being called only when model was already saved.
So is there a way to validate the model based on several fields (both saved in DB and new ones) before saving it, while using model.update()
method?
As a summary:
{ active: false, avatar: null }
User.update({ _id: id }, { $set: { avatar: 'user1.png' } });
{ active: false, avatar: 'user1.png' }
Validation is asynchronously recursive; when you call Model#save, sub-document validation is executed as well. If an error occurs, your Model#save callback receives it. Validation is customizable.
A Validator implementation must contain a constructor, a set of accessor methods for any attributes on the tag, and a validate method, which overrides the validate method of the Validator interface.
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.
Mongoose is an Object Data Modeling (ODM) library for MongoDB and Node. js. It manages relationships between data, provides schema validation, and is used to translate between objects in code and the representation of those objects in MongoDB. MongoDB is a schema-less NoSQL document database.
Due to limitation of working with update()
I've decided to solve the problem this way:
update()
So instead of
User.update({ _id: id }, { $set: { avatar: 'user1.png' } });
I use
User.findOne({ _id: id })
.then((user) => {
user.avatar = 'user1.png';
user.save();
});
In this case custom validators work as expected.
P.S. I choose this answer as a correct one for me, but I will give bounty to the most relevant answer.
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