mongoose 文档(五) Validation

Validation

在我们进入验证语法的细节之前,请记住以下规则:

  • Validation是在SchemaType定义
  • Validation是中间件的内部组件
  • Validation发生在document试图在默认值应用之后保存的时候。
  • Validation不在未定义的值运行,唯一例外是必要的验证器
  • Validation是异步递归的,当你调用Model#save,子文档验证也会执行。如果发生错误,Model#save回调会接收它。
  • 验证支持完全定制

 

内置验证器

mongoose有几个内置验证器。

上面的每一个验证器链接提供关于如何使用它们和定制错误信息。

var schema = new mongoose.Schema({
    name:{
        type:'String',
        required: true,
        maxlength: 10,
        match: /^a/   
    },
    date: {
        type: Date,
        default: Date.now
    },
    age:{
        type:'Number',
        min:18,       //年龄最小18
        max:120     //年龄最大120
    },
    city:{
        type:'String',
        enum:['北京','上海']  //只能是北京、上海人
    },
});

 

自定义验证器

如果内置验证器不够,validation能够完全可以满足你的需求。

自定义验证通过函数传递声明。你能在SchemaType#validate() API 文档找到如何实现它的详细说明。

var userSchema = new Schema({
  phone: {
    type: String,
    validate: {
      validator: function(v) {
        return /d{3}-d{3}-d{4}/.test(v);
      },
      message: '{VALUE} is not a valid phone number!'
    }
  }
});

var User = mongoose.model('user', userSchema);

var u = new User();

u.phone = '555.0123';
// Prints "ValidationError: 555.0123 is not a valid phone number!"
console.log(u.validateSync().toString());

u.phone = '201-555-0123';
// Prints undefined - validation succeeded!
console.log(u.validateSync());

 

错误验证

Validation失败后返回的Errors包含一个持有实际ValidatorErrors的errors对象。每个ValidatorError有kind、path、value和message属性。

var toySchema = new Schema({
  color: String,
  name: String
});

var Toy = mongoose.model('Toy', toySchema);

Toy.schema.path('color').validate(function (value) {
  return /blue|green|white|red|orange|periwinkle/i.test(value);
}, 'Invalid color');

var toy = new Toy({ color: 'grease'});

toy.save(function (err) {
  // err is our ValidationError object
  // err.errors.color is a ValidatorError object
  
  console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color with value `grease`'
  console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color with value `grease`'
  console.log(err.errors.color.kind)  // prints "Invalid color"
  console.log(err.errors.color.path)  // prints "color"
  console.log(err.errors.color.value) // prints "grease"
  console.log(err.name) // prints "ValidationError"
  console.log(err.message) // prints "Validation failed"
});

 

经过验证错误,该文件将有相同的错误属性:

toy.errors.color.message === err.errors.color.message

 

同步验证

 Validation默认是异步的。mongoose用独立的 process.nextTick() 调用估计每个独立path  ,这确保了如果有许多路径要验证, validation不会阻塞event loop。可是,mongoose的内置验证器都是同步的,通常它比同步验证更方便。

 

mongoose document也有validateSync() 方法,如果有错误它返回ValidationError否则返回falsy。注意,validatesync()执行同步的验证器。自定义异步验证器不会执行。

var toySchema = new Schema({
  color: String,
  name: String
});

var Toy = mongoose.model('Toy', toySchema);

Toy.schema.path('color').validate(function (value) {
  return /blue|green|white|red|orange|periwinkle/i.test(value);
}, 'Invalid color');

var toy = new Toy({ color: 'grease'});

// `error` is a ValidationError analogous to the one from `validate()`
var error = toy.validateSync();

// prints 'Validator "Invalid color" failed for path color with value `grease`'
console.log(error.errors.color.message);

 

 

修改验证

mongoose也支持update() 和 findOneAndUpdate() 操作的验证。在Mongoose 4.x,update验证器默认是关闭的 - 你需要指定runValidators 选项。

var toySchema = new Schema({
  color: String,
  name: String
});

var Toy = mongoose.model('Toy', toySchema);

Toy.schema.path('color').validate(function (value) {
  return /blue|green|white|red|orange|periwinkle/i.test(value);
}, 'Invalid color');

Toy.update({}, { color: 'bacon' }, { runValidators: true }, function (err) {
  console.log(err.errors.color.message); // prints 'Validator "Invalid color" failed for path color with value `bacon`'
});

 

修改验证器和document验证器直接有两个个区别。在上面的颜色验证器函数,当使用document验证器时它引用被验证的document。可是,当运行修改验证器时,被修改的document可能不在服务器的内存,因此在默认情况下这个值未定义。然而,你可以设置上下文选项为'query'来使它引用基础query。

Toy.schema.path('color').validate(function (value) {
  this.schema; // refers to the query's schema if you set the `context` option
  return /blue|green|white|red|orange|periwinkle/i.test(value);
}, 'Invalid color');

var options = { runValidators: true, context: 'query' };
Toy.update({}, { color: 'bacon' }, options, function (err) {
  console.log(err.errors.color.message); // prints 'Validator "Invalid color" failed for path color with value `bacon`'
});

 

另一个主要差别是修改验证器只运行在修改中指定的path。例如,在下面的例子,因为在修改操作中没有指定'name',更新validation会成功。

var toySchema = new Schema({
  color: String,
  name: { type: String, required: true }
});

var Toy = mongoose.model('Toy', toySchema);

Toy.update({}, { color: 'blue' }, { runValidators: true }, function(err) {
  // Operation succeeds despite the fact that 'name' is not specified
});

使用修改验证器时,当你 $unset 键的时候,必要的验证器才会失败。

var unsetOp = { $unset: { name: 1 } };
Toy.update({}, unsetOp, { runValidators: true }, function(err) {
  // Operation fails because 'name' is required
});

 最后值得注意的一个细节:修改验证器只在$set和$unset操作运行。例如,不管number的值是多少,下面的修改都会成功。

var testSchema = new Schema({
  number: { type: Number, max: 0 },
});

var Test = mongoose.model('Test', testSchema);

Test.update({}, { $inc: { number: 1 } }, { runValidators: true }, function (err) {
  // There will never be a validation error here
});

 

posted on 2016-02-09 00:53  Surahe  阅读(2087)  评论(0编辑  收藏  举报