Skip to content

Latest commit

 

History

History
229 lines (167 loc) · 8.78 KB

File metadata and controls

229 lines (167 loc) · 8.78 KB

Validation

Before we get into the specifics of validation syntax, please keep the following rules in mind:

  • Validation is defined in the SchemaType
  • Validation is middleware. Mongoose registers validation as a pre('save') hook on every schema by default.
  • Validation always runs as the first pre('save') hook. This means that validation doesn't run on any changes you make in pre('save') hooks.
  • You can disable automatic validation before save by setting the validateBeforeSave option
  • You can manually run validation using doc.validate() or doc.validateSync()
  • You can manually mark a field as invalid (causing validation to fail) by using doc.invalidate(...)
  • Validators are not run on undefined values. The only exception is the required validator.
  • When you call Model#save, Mongoose also runs subdocument validation. If an error occurs, your Model#save promise rejects
  • Validation is customizable
[require:Validation$]

Built-in Validators

Mongoose has several built-in validators.

Each of the validator links above provide more information about how to enable them and customize their error messages.

[require:Built-in Validators]

Custom Error Messages

You can configure the error message for individual validators in your schema. There are two equivalent ways to set the validator error message:

  • Array syntax: min: [6, 'Must be at least 6, got {VALUE}']
  • Object syntax: enum: { values: ['Coffee', 'Tea'], message: '{VALUE} is not supported' }

Mongoose also supports rudimentary templating for error messages. Mongoose replaces {VALUE} with the value being validated.

[require:Custom Error Messages]

The unique Option is Not a Validator

A common gotcha for beginners is that the unique option for schemas is not a validator. It's a convenient helper for building MongoDB unique indexes. See the FAQ for more information.

[require:The `unique` Option is Not a Validator]

Custom Validators

If the built-in validators aren't enough, you can define custom validators to suit your needs.

Custom validation is declared by passing a validation function. You can find detailed instructions on how to do this in the SchemaType#validate() API docs.

[require:Custom Validators]

Async Custom Validators

Custom validators can also be asynchronous. If your validator function returns a promise (like an async function), mongoose will wait for that promise to settle. If the returned promise rejects, or fulfills with the value false, Mongoose will consider that a validation error.

[require:Async Custom Validators]

Validation Errors

Errors returned after failed validation contain an errors object whose values are ValidatorError objects. Each ValidatorError has kind, path, value, and message properties. A ValidatorError also may have a reason property. If an error was thrown in the validator, this property will contain the error that was thrown.

[require:Validation Errors]

Cast Errors

Before running validators, Mongoose attempts to coerce values to the correct type. This process is called casting the document. If casting fails for a given path, the error.errors object will contain a CastError object.

Casting runs before validation, and validation does not run if casting fails. That means your custom validators may assume v is null, undefined, or an instance of the type specified in your schema.

[require:Cast Errors]

By default, Mongoose cast error messages look like Cast to Number failed for value "pie" at path "numWheels". You can overwrite Mongoose's default cast error message by the cast option on your SchemaType to a string as follows.

[require:Cast Error Message Overwrite]

Mongoose's cast error message templating supports the following parameters:

  • {PATH}: the path that failed to cast
  • {VALUE}: a string representation of the value that failed to cast
  • {KIND}: the type that Mongoose attempted to cast to, like 'String' or 'Number'

You can also define a function that Mongoose will call to get the cast error message as follows.

[require:Cast Error Message Function Overwrite]

Global SchemaType Validation

In addition to defining custom validators on individual schema paths, you can also configure a custom validator to run on every instance of a given SchemaType. For example, the following code demonstrates how to make empty string '' an invalid value for all string paths.

[require:Global SchemaType Validation]

Required Validators On Nested Objects

Defining validators on nested objects in mongoose is tricky, because nested objects are not fully fledged paths.

[require:Required Validators On Nested Objects]

Update Validators

In the above examples, you learned about document validation. Mongoose also supports validation for update(), updateOne(), updateMany(), and findOneAndUpdate() operations. Update validators are off by default - you need to specify the runValidators option.

To turn on update validators, set the runValidators option for update(), updateOne(), updateMany(), or findOneAndUpdate(). Be careful: update validators are off by default because they have several caveats.

[require:Update Validators$]

Update Validators and this

There are a couple of key differences between update validators and document validators. In the color validation function below, this refers to the document being validated when using document validation. However, when running update validators, this refers to the query object instead of the document. Because queries have a neat .get() function, you can get the updated value of the property you want.

[require:Update Validators and `this`]

Update Validators Only Run On Updated Paths

The other key difference is that update validators only run on the paths specified in the update. For instance, in the below example, because 'name' is not specified in the update operation, update validation will succeed.

When using update validators, required validators only fail when you try to explicitly $unset the key.

[require:Update Validators Only Run On Updated Paths]

Update Validators Only Run For Some Operations

One final detail worth noting: update validators only run on the following update operators:

  • $set
  • $unset
  • $push
  • $addToSet
  • $pull
  • $pullAll

For instance, the below update will succeed, regardless of the value of number, because update validators ignore $inc.

Also, $push, $addToSet, $pull, and $pullAll validation does not run any validation on the array itself, only individual elements of the array.

[require:Update Validators Only Run For Some Operations]

Next Up

Now that we've covered Validation, let's take a look at Middleware.