一句话来概括:
把校验函数(校验器),在Schema中完成注册,并在钩子中进行调用,使用复杂的Error包装校验结果,在CRUD的回调中由用户决定如何处理的校验框架。
一、校验器
是一个返回boolean的函数,形式如下:
function validateName(v) {
return /\d{3}-\d{3}-\d{4}/.test(v);
}
function validateCreated(v) {
return [true|false]
}
两种校验器:
- built-in validator
- custom validator(以上的校验器,为custom validator)
二、校验器的注册:
- built-in validator
var breakfastSchema = new Schema({
eggs: {
type: Number,
min: [6, 'Too few eggs'],
max: 12
},
bacon: {
type: Number,
required: [true, 'Why no bacon?']
},
drink: {
type: String,
enum: ['Coffee', 'Tea'],
required: function() {
return this.bacon > 3;
}
}
});
- custom validator
var userSchema = new Schema({
phone: {
type: String,
validate: {
validator: function(v) {
return /\d{3}-\d{3}-\d{4}/.test(v);
},
message: props => `${props.value} is not a valid phone number!`
},
required: [true, 'User phone number required']
}
});
三、校验的时机
在schema的pre hook的回调函数,使用校验器,以下是我完成的示意代码(实际使用时,需要进行递归式校验)
var toySchema = new Schema({ name: String, created: Date });
toySchema.pre('save', function(next) {
var err=new MogooseError();
if(!validateName(this.name)) err.errors.name=new MongooseError({msg:'xxx'});
if(!validateCreated(this.created)) err.errors.created=new MongooseError({msg:'xxx'});
if(err.errors===null) next(); //通过
throw err;//未通过
});
四、校验未通过的处理
- 如果校验通过时,则执行save操作(添加或更新)。
- 如果校验没有通过时,则上面的“MongooseError”对象,将会出现在回调函数的第一个参数或promise的reject的参数上。
五、Error的结构分析
构造器: mongoose.Error指向的函数,其名称为:MongooseError。
error对象的name:
(1)name: ValidationError,此时表明校验的对象是由Schema定义的Model产生的对象(简单说:是document对象)。
(2)name: CastError,此时表明检验的对象是简单JS对象或原生数据类型(简单说:是非document对象)ValidationError对象:
即name是ValidationError的MongooseError对象。
它会有一个errors引用,其指向到一个Object,未通过校验的field会以fieldName挂载到errors上,
(1)并指向到一个CastError对象(name是castError的ValidationError)。
(2)如果field的类型是document时,会指向到一个ValidationError对象(其包含一个errors,如此递归,最终指向到一个CastError)。CastError对象:
即name是CastError的MongooseError对象,其属性如下:
(1)message: String类型的信息。
(2)value: 当前值
(3)kind: 在schema中定义的类型