【问题标题】:mongoose custom validation using 2 fields使用 2 个字段的猫鼬自定义验证
【发布时间】: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 是一个比较两个日期的函数。

【问题讨论】:

    标签: node.js mongodb express mongoose


    【解决方案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);
        

        【讨论】:

        猜你喜欢
        • 2016-09-01
        • 1970-01-01
        • 2014-02-23
        • 1970-01-01
        • 2017-05-03
        • 2014-03-04
        • 2019-03-15
        • 2019-03-27
        相关资源
        最近更新 更多