Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongodb upsert throwing DuplicateKeyException

I do get this error [2] from time to time when attempting to upsert (increment or insert) a document using method [1].

[1]

public NGram save(final NGram ngram) {
    Criteria cr = where("_id").is(ngram.getNgram())
            .and("f3c").is(ngram.getF3c())
            .and("tokCount").is(ngram.getTokCount())
            .and("first").is(ngram.getFirst())
            ;
    if( ngram.getTokCount() > 1 ) {
        cr.and("second").is(ngram.getSecond());
    }
    if( ngram.getTokCount() > 2 ) {
        cr.and("third").is(ngram.getThird());
    }
    final Query qry = new Query( cr );
    final Update updt = new Update().inc("count", ngram.getCount());
    template.upsert(qry, updt, NGram.class);
    return ngram;
}

[2]

Caused by: org.springframework.dao.DuplicateKeyException: E11000 duplicate key error index: sytrue.ngram.$_id_  dup key: { : "page two" }; nested exception is com.mongodb.MongoException$DuplicateKey: E11000 duplicate key error index: sytrue.ngram.$_id_  dup key: { : "page two" }
at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:52)
at org.springframework.data.mongodb.core.MongoTemplate.potentiallyConvertRuntimeException(MongoTemplate.java:1665)
at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:390)
at org.springframework.data.mongodb.core.MongoTemplate.doUpdate(MongoTemplate.java:920)
at org.springframework.data.mongodb.core.MongoTemplate.upsert(MongoTemplate.java:894)
at com.sytrue.ngram.repo.impl.NGramRepositoryImpl.save(NGramRepositoryImpl.java:43)
at sun.reflect.GeneratedMethodAccessor41.invoke(Unknown Source)

Upsert should never return me this exception. Am I right?

like image 692
biliboc Avatar asked May 09 '13 15:05

biliboc


People also ask

How does MongoDB Upsert work?

Here in MongoDB, the upsert option is a Boolean value. Suppose the value is true and the documents match the specified query filter. In that case, the applied update operation will update the documents. If the value is true and no documents match the condition, this option inserts a new document into the collection.

How do I avoid duplicate errors in MongoDB?

If you ever faced this error all you need to do is to check your model carefully and find out that is there any unique key set true by you and if it is not necessary then simply remove the unique key from the model or otherwise set a unique value if it is necessary to be unique.

Is MongoDB Upsert Atomic?

Upsert is not atomic. This is insinuated by the Mongo documentation: https://docs.mongodb.org/v3.0/reference/method/db.collection.update/. To avoid inserting the same document more than once, only use upsert: true if the query field is uniquely indexed.

Is Upsert Atomic?

The basic upsert function has been enhanced to support an Atomic upsert capability. This enhancement permits Teradata TPump to perform single‑row upserts in a single pass. This one‑pass logic adopts the upsert‑handling technique used by MultiLoad.


1 Answers

The issue that I am just guessing might be following :

You are doing find operations based on many criteria. That means if it fails because of any mismatch of a param ( in criteria ) then it will try to insert the document.

So, chances are there, that you are trying to update the same document with same _id but some of the other criteria is not matching, causing it to insert again which will cause duplicate key exception. Consider the below example

test:Mongo > db.example.update({ _id : 1, a : 1, b : 1},{ $set : {d : 1}}, true, false)
test:Mongo > db.example.find()
{ "_id" : 1, "a" : 1, "b" : 1, "d" : 1 }
test:Mongo > db.example.update({ _id : 1, a : 1, b : 2},{ $set : {d : 1}}, true, false)
E11000 duplicate key error index: test.example.$_id_  dup key: { : 1.0 }
like image 72
Abhishek Kumar Avatar answered Oct 20 '22 20:10

Abhishek Kumar