使用 2 个字段的猫鼬自定义验证
Posted
技术标签:
【中文标题】使用 2 个字段的猫鼬自定义验证【英文标题】:mongoose custom validation using 2 fields 【发布时间】:2014-07-08 17:48:18 【问题描述】:我想使用 mongoose 自定义验证来验证 endDate 是否大于 startDate。如何访问 startDate 值?使用this.startDate时,不起作用;我不确定。
var a = new Schema(
startDate: Date,
endDate: Date
);
var A = mongoose.model('A', a);
A.schema.path('endDate').validate(function (value)
return diff(this.startDate, value) >= 0;
, 'End Date must be greater than Start Date');
diff
是一个比较两个日期的函数。
【问题讨论】:
【参考方案1】:您可以使用 Mongoose 'validate'
middleware 做到这一点,这样您就可以访问所有字段:
ASchema.pre('validate', function(next)
if (this.startDate > this.endDate)
next(new Error('End Date must be greater than Start Date'));
else
next();
);
请注意,当调用 next
报告验证失败时,您必须将验证错误消息包装在 javascript Error
对象中。
【讨论】:
我的控制器中有 nodejs exports.create = function (req, res, next) var a = new A(req.body); // 我在这里添加了你的代码,但它不起作用 newEvent.save(function(err) if (err) return res.json(400, err); return res.json(message:'success' ); ); @JohnnyHK:我应该在哪里添加您的代码示例谢谢 这比公认的答案更干净,谢谢@JohnnyHK 我试过了但是错误没有返回到entity.save()
回调。
@AdrienG 如果您仍需要帮助,请继续发布一个包含完整详细信息的新问题。
也许这是我的错,但我找到了另一种方法:我改用 this.invalidate('myField', 'my error message.', this.myField);
所以没关系,谢谢 :)【参考方案2】:
原始问题已接受答案的另一种选择是:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
// schema definition
var ASchema = new Schema(
startDate:
type: Date,
required: true
,
endDate:
type: Date,
required: true,
validate: [dateValidator, 'Start Date must be less than End Date']
);
// function that validate the startDate and endDate
function dateValidator(value)
// `this` is the mongoose document
return this.startDate <= value;
【讨论】:
太棒了!如果您需要两个字段之一,您可以在必填字段上创建验证,但请通过this
检查您需要的内容。
此选项在使用带有 runValidators 选项的 .findOneAndUpdate 时失败。这有错误的上下文,所以 .startDate 将不可用:(【参考方案3】:
我想通过点击 this.invalidate 来扩展 @JohnnyHK 的可靠答案(谢谢):
Schema.pre('validate', function (next)
if (this.startDate > this.endDate)
this.invalidate('startDate', 'Start date must be less than end date.', this.startDate);
next();
);
这会将所有验证错误保存在 mongoose.Error.ValidationError 错误中。有助于保持错误处理程序标准化。希望这会有所帮助。
【讨论】:
正是我需要的!现在我只需要弄清楚为什么猫鼬在保存之前没有点击验证钩子...... 无视上述,这个解决方案是完美的。应该是被接受的。谢谢@kognizant !!!【参考方案4】:您可以尝试将日期戳嵌套在父对象中,然后验证父对象。例如:
//create a simple object defining your dates
var dateStampSchema =
startDate: type:Date,
endDate: type:Date
;
//validation function
function checkDates(value)
return value.endDate < value.startDate;
//now pass in the dateStampSchema object as the type for a schema field
var schema = new Schema(
dateInfo: type:dateStampSchema, validate:checkDates
);
【讨论】:
【参考方案5】:在验证器中使用“this”对我有用 - 在这种情况下,当检查电子邮件地址的唯一性时,我需要访问当前对象的 id,以便我可以将其排除在计数之外:
var userSchema = new mongoose.Schema(
id: String,
name: type: String, required: true,
email:
type: String,
index:
unique: true, dropDups: true
,
validate: [
validator: validator.isEmail, msg: 'invalid email address',
validator: isEmailUnique, msg: 'Email already exists'
],
facebookId: String,
googleId: String,
admin: Boolean
);
function isEmailUnique(value, done)
if (value)
mongoose.models['users'].count( _id: '$ne': this._id , email: value , function (err, count)
if (err)
return done(err);
// If `count` is greater than zero, "invalidate"
done(!count);
);
【讨论】:
【参考方案6】:这是我使用的解决方案(感谢@shakinfree 的提示):
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
// schema definition
var ASchema = new Schema(
dateSchema :
type:
startDate:type:Date, required: true,
endDate:type:Date, required: true
,
required: true,
validate: [dateValidator, 'Start Date must be less than End Date']
);
// function that validate the startDate and endDate
function dateValidator (value)
return value.startDate <= value.endDate;
module.exports = mongoose.model('A', ASchema);
【讨论】:
谨慎使用这种方法,因为 4.01 中存在错误 github.com/Automattic/mongoose/issues/2814以上是关于使用 2 个字段的猫鼬自定义验证的主要内容,如果未能解决你的问题,请参考以下文章