Mongoose Validation
Mongoose Validation
사실 Database Layer 에서 Validation 을 하는건 좋은 방법은 아닌 것 같습니다. Front 단에서도 필요하고, Back 단에서도 필요하지만, Back 단에서는 가능하다면 Server Application 단에서 처리하는게 더 나아 보입니다. 저 처럼 무식하게 mongoose validation 을 검색하신 분이 아니라면, 삽질 시간을 줄여드리기 위해서 조용히 express-validator 를 추천해 드립니다.
1. mongoose.Schema.path.validate
User.path('email').validate(function(v, fn) {
// Make sure the email address is not already registered
var UserModel = mongoose.model('User');
UserModel.find({'email': v.toLowerCase()}, function (err, emails) {
fn(err || emails.length === 0);
});
}, 'Email is already registered');
var toySchema = new Schema({
color: String,
name: String
});
var Toy = mongoose.model('Toy', toySchema);
Toy.schema.path('color').validate(function (value) {
return /blue|green|white|red|orange|periwinkle/i.test(value);
}, 'Invalid color');
var toy = new Toy({ color: 'grease'});
toy.save(function (err) {
// err is our ValidationError object
// err.errors.color is a ValidatorError object
console.log(err.errors.color.message) // prints 'Validator "Invalid color" failed for path color with value `grease`'
console.log(String(err.errors.color)) // prints 'Validator "Invalid color" failed for path color with value `grease`'
console.log(err.errors.color.type) // prints "Invalid color"
console.log(err.errors.color.path) // prints "color"
console.log(err.errors.color.value) // prints "grease"
console.log(err.name) // prints "ValidationError"
console.log(err.message) // prints "Validation failed"
});
2. Schema Validation
function validator (val) { return val == 'something'; }
var custom = [validator, 'validation failed']
new Schema({ name: { type: String, validate: custom }});
var genders = 'MALE FEMALE'.split(' ')
var UserSchema = mongoose.Schema({
name: {type: String, required: true}, // 1. Required validation
age: {type: Number, min: 16, max: 60}, // 2. Minimum and Maximum value validation
gender: {type: String, enum: genders}, // 3. ENUM validation
email: {type: String, match: /\S+@\S+\.\S+/} // 4. Match validation via regex
});
var User = mongoose.model('User', UserSchema);
new User({age: 25}).validate(function (error) {
console.log("ERROR: ", error); // Error for Name Field because its marked as Required.
});
new User({name: "Amit Thakkar", age:15}).validate(function (error) {
console.log("ERROR: ", error); // Error for Age Field, age is less than Minimum value.
});
new User({name: "Amit Thakkar", age:61}).validate(function (error) {
console.log("ERROR: ", error); // Error for Age Field, age is more than Maximum value.
});
new User({name: "Amit Thakkar", age:25, gender:"male"}).validate(function (error) {
console.log("ERROR: ", error); // Error for Gender Field, male does not match with ENUM.
});
new User({name: "Amit Thakkar", age:25, gender:"MALE", email:"amit.kumar@intelligrape"}).validate(function (error) {
console.log("ERROR: ", error); // Error for Invalid Email id.
});
new User({name: "Amit Thakkar", age:25, gender:"MALE", email:"[email protected]"}).validate(function (error) {
console.log("ERROR: ", error); // Error will be undefined
});
Schema.pre
schema.pre("save", function(next) {
var self = this;
model.findOne({email : this.email}, 'email', function(err, results) {
if(err) {
next(err);
} else if(results) {
console.warn('results', results);
self.invalidate("email", "email must be unique");
next(new Error("email must be unique"));
} else {
next();
}
});
});
참고로, pre 에서 function(next, done) 콜백을 사용할수도 있는데, 이건 parallel middleware callback 입니다. 자세한 내용은 여기 를 참고하세요
Tip: set
function toLower (v) {
return v.toLowerCase();
}
var UserSchema = new Schema({
email: { type: String, set: toLower }
});
References
- http://nraj.tumblr.com/post/38706353543/handling-uniqueness-validation-in-mongo-mongoose
- http://mongoosejs.com/docs/validation.html
- http://stackoverflow.com/questions/11872556/what-am-i-doing-wrong-in-this-mongoose-unique-pre-save-validation
- http://stackoverflow.com/questions/13582862/mongoose-pre-save-async-middleware-not-working-as-expected
- http://www.intelligrape.com/blog/2014/02/19/validation-with-mongoose/
- http://stackoverflow.com/questions/11325372/mongoose-odm-change-variables-before-saving
Array