mongoose validación personalizada utilizando 2 campos

Deseo usar la validación personalizada de mongoose para validar si endDate es mayor que startDate. ¿Cómo puedo acceder al valor startDate? Al usar this.startDate , no funciona; Me vuelvo indefinido

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 es una función que compara dos fechas.

Podría tratar de anidar sus sellos de fecha en un objeto principal y luego validar el padre. Por ejemplo, algo como:

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

Puedes hacerlo usando 'validate' middleware 'validate' Mongoose para que tengas acceso a todos los campos:

 ASchema.pre('validate', function(next) { if (this.startDate > this.endDate) { next(new Error('End Date must be greater than Start Date')); } else { next(); } }); 

Tenga en cuenta que debe envolver su mensaje de error de validación en un objeto JavaScript Error al llamar a next para informar un error de validación.

Una alternativa a la respuesta aceptada para la pregunta original es:

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

Quería ampliar la sólida respuesta de @JohnnyHK (gracias) tocando en this.invalidate:

 Schema.pre('validate', function (next) { if (this.startDate > this.endDate) { this.invalidate('startDate', 'Start date must be less than end date.', this.startDate); } next(); }); 

Esto mantiene todos los errores de validación dentro de un error mongoose.Error.ValidationError. Ayuda a mantener los manejadores de errores estandarizados. Espero que esto ayude.

El uso de ‘esto’ dentro del validador funciona para mí; en este caso, al verificar la exclusividad de la dirección de correo electrónico, necesito acceder al ID del objeto actual para poder excluirlo del recuento:

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

Esta es la solución que utilicé (gracias a @shakinfree por la pista):

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