To make MongoDB database manipulation easy, we can use the Mongoose NPM package to make working with MongoDB databases easier.
In this article, we’ll look at how to use Mongoose to manipulate our MongoDB database.
Async Custom Validators
We can add custom validators that are async.
For example, we can write:
async function run() {
const { createConnection, Schema } = require('mongoose');
const connection = createConnection('mongodb://localhost:27017/test');
const userSchema = new Schema({
email: {
type: String,
validate: {
validator(v) {
return Promise.resolve(/(.+)@(.+){2,}.(.+){2,}/.test(v));
},
message: props => `${props.value} is not a email!`
},
required: [true, 'Email is required']
}
});
const User = connection.model('User', userSchema);
const user = new User();
user.email = 'test';
try {
await user.validate();
} catch (error) {
console.log(error);
}
}
run();
to add the validator
method to our method that returns a promise instead of a boolean directly.
Then we can use the validate
method to validate the values we set.
And then we can catch validation errors with the catch
block.
We can get the message from the errors
property in the error
object.
Validation Errors
Errors returned after validation has an errors
object whose values are ValidatorError
objects.
ValidatorError
objects have kind
, path
, value
, and message
properties.
They may also have a reason
property.
If an error is thrown in the validator, the property will have the error that was thrown.
For example, we can write:
async function run() {
const { createConnection, Schema } = require('mongoose');
const connection = createConnection('mongodb://localhost:27017/test');
const toySchema = new Schema({
color: String,
name: String
});
const validator = function (value) {
return /red|white|gold/i.test(value);
};
toySchema.path('color').validate(validator,
'Color `{VALUE}` not valid', 'Invalid color');
toySchema.path('name').validate((v) => {
if (v !== 'special toy') {
throw new Error('I want special toy');
}
return true;
}, 'Name `{VALUE}` is not valid');
const Toy = connection.model('Toy', toySchema);
const toy = new Toy();
toy.color = 'green';
toy.name = 'abc';
toy.save((err) => {
console.log(err);
})
}
run();
We have the validator
function that returns true
or false
depending on the validity of the value.
The name
value also has a validator added to it by passing a callback into the validate
method to validate the name
field.
Cast Errors
Mongoose tries to coerce values into the correct type before validators are run.
If data coercion fails, then the error.errors
object will have a CastError
object.
For example, if we have:
async function run() {
const { createConnection, Schema } = require('mongoose');
const connection = createConnection('mongodb://localhost:27017/test');
const vehicleSchema = new Schema({
numWheels: { type: Number, max: 18 }
});
const Vehicle = connection.model('Vehicle', vehicleSchema);
const doc = new Vehicle({ numWheels: 'abc' });
const err = doc.validateSync();
console.log(err);
}
run();
Since we set numWheels
to a non-numeric string, we’ll get a CastError
as the value of the err
object.
Conclusion
There are many ways to do validation with Mongoose schema fields with Mongoose.