Mongoose unique validation error type


Question

I'm using this schema with mongoose 3.0.3 from npm:

var schema = new Schema({

    _id: Schema.ObjectId,
    email: {type: String, required: true, unique: true}

});

If I try to save a email that is already in db, I expect to get a ValidationError like if a required field is omitted. However this is not the case, I get a MongoError: E11000 duplicate key error index.

Which is not a validation error (happens even if I remove the unique:true).

Any idea why?

1
19
11/27/2012 10:40:40 AM

Accepted Answer

I prefer putting it in path validation mechanisms, like

UserSchema.path('email').validate(function(value, done) {
    this.model('User').count({ email: value }, function(err, count) {
        if (err) {
            return done(err);
        } 
        // If `count` is greater than zero, "invalidate"
        done(!count);
    });
}, 'Email already exists');

Then it'll just get wrapped into ValidationError and will return as first argument when you call validate or save .

27
2/27/2014 10:30:06 PM

This is expected behavior

The unique: true is equivalent to setting an index in mongodb like this:

db.myCollection.ensureIndex( { "email": 1 }, { unique: true } )

To do this type of validation using Mongoose (Mongoose calls this complex validation- ie- you are not just asserting the value is a number for example), you will need to wire in to the pre-save event:

mySchema.pre("save",function(next, done) {
    var self = this;
    mongoose.models["User"].findOne({email : self.email},function(err, results) {
        if(err) {
            done(err);
        } else if(results) { //there was a result found, so the email address exists
            self.invalidate("email","email must be unique");
            done(new Error("email must be unique"));
        } else {
            done();
        }
    });
    next();
});

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon