Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unique index validation error not throwing #1225

Closed
mgcrea opened this issue Nov 27, 2012 · 14 comments
Closed

Unique index validation error not throwing #1225

mgcrea opened this issue Nov 27, 2012 · 14 comments

Comments

@mgcrea
Copy link
Contributor

mgcrea commented Nov 27, 2012

I'm using this schema with latest npm mongoose:

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

@aheckmann
Copy link
Collaborator

Setting unique: true creates an unique index in MongoDB. MongoError: E11000 duplicate key error index is not a Mongoose validation error, it comes from MongoDB.

aheckmann added a commit that referenced this issue Dec 6, 2012
@madcampos
Copy link

how can i catch this error?

@aheckmann
Copy link
Collaborator

doc.save(function (err) {
  // handle err
})

@madcampos
Copy link

i tryed it and the error didin't bubbled.
for now i'm using this function to do validation:

/**
 * Unique Validation
 * @param {Schema} schema The schema to witch validate.
 * @param {Model} model The model to perform searches.
 * @param {String} field The field name to search for duplicated entries.
 * @throws {E11000} Duplicate key.
 */
function uniqueValidator(schema, model, field) {
    schema.pre('save', function(next){
        var toValidate = {};
        toValidate[field] = this[field];
        model.findOne(toValidate, field, function(err, res){
            if (err) {
                next(err);
            } else if (res) {
                err = new Error('Duplicate key.');
                err.code = 'E11000';
                next(err);
            } else {
                next();
            }
        });
    });
}

it's not best practices but is working. i just wanted to know if there was some "cleaner"/best way to do this. thanks.
ps: i'm using updated versions of both mongo and mongoose

@aheckmann
Copy link
Collaborator

check the indexes that exist in your collection to see if the unique index exists.

  1. open the mongo shell
  2. use yourDatabase
  3. db.yourCollection.getIndexes()

You should see all indexes that exist on your collection. Check to see if your unique index exists.

If it does, something is very wrong.

If it doesn't (more likely), there are probably duplicate values in the collection already which will prevent a unique index from being created. You can check this by adding a listener to your models index event and checking for errors:

var schema = Schema(..);
var YourModel = mongoose.model('YourModel', schema);
YourModel.on('index', function (err) {
  if (err) console.error(err);
})

http://mongoosejs.com/docs/api.html#model_Model.ensureIndexes
http://mongoosejs.com/docs/guide.html#indexes

@madcampos
Copy link

thanks. that's what heppened, first i added non-unique values, and then changed the code adding unique: true to them.
sorry for the question, but how do i abort the save operation?
it's still saving on the db.

@aheckmann
Copy link
Collaborator

I don't understand your question.

@madcampos
Copy link

as there is a duplicate key and it have to be unique, how do i stop the saving operation so it isin't saved, or what alternative should i try?

@francoiscolas
Copy link

I think it would be great if the unique error was thrown the same way of other validators.

Mongoose could check if the error code is 11001 (http://www.mongodb.org/about/contributors/error-codes/) and then call something like: doc.invalidate(path, "unique").

I tried doing this with schema.post('save', ...) but it seems that no post handlers are called on error.

@madcampos
Copy link

sorry, the error was mine.
i dumped the database and started fresh with the unique:true setting set, the error was thrown in my save operation and the object didn't got saved (the behavior i was expecting).
i'm really sorry for the inconvenience.

@blakehaswell
Copy link

For anyone interested, I’ve added a plugin which checks the DB prior to saving and throws a Mongoose validation error if any of your unique constraints will be violated:
https://github.com/blakehaswell/mongoose-unique-validator

@lukejacksonn
Copy link

I had this issue and it was due to already existing duplicate values in my index (as pointed out in aheckmann's comment on Feb 1, 2013). I was reading from here http://mongoosejs.com/docs/api.html#schematype_SchemaType-required where it mentions the error, but fails to mention about already exiting duplicates preventing the uniques index from being created in the first place. Might be worth updating the doc to mention this too!

@ahmedkrdzalic
Copy link

Can we make a custom message option for this error just like we can handle the "require" attribute?
I am willing to contribute to the project.

@vkarpov15
Copy link
Collaborator

@ahmedkrdzalic we opened a new issue to track that feature request. In the meantime, please check out this plugin: https://www.npmjs.com/package/mongoose-beautiful-unique-validation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants