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?
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.
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.
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.
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.
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 }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With