使用2个字段进行猫鼬自定义验证

时间:2014-05-20 12:46:12

标签: node.js mongodb express mongoose

我想使用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是一个比较两个日期的函数。

6 个答案:

答案 0 :(得分:75)

您可以使用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();
    }
});

请注意,在调用Error报告验证失败时,必须将验证错误消息包装在JavaScript next对象中。

答案 1 :(得分:28)

原始问题的已接受答案的替代方法是:

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;
}

答案 2 :(得分:25)

您可以尝试在父对象中嵌套日期戳,然后验证父级。例如:

//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}
});

答案 3 :(得分:18)

我希望通过点击此内容来扩展@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错误中。有助于保持错误处理程序的标准化。希望这会有所帮助。

答案 4 :(得分: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);
    });
  }
}

答案 5 :(得分:1)

这是我使用的解决方案(感谢@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);