Categories
MongoDB

Using MongoDB with Mongoose — Async Validators and Validation Errors

Spread the love

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.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *