2013-05-09 7 views
9

Ich bekomme diesen Fehler [2] von Zeit zu Zeit beim Versuch, ein Dokument mit der Methode [1] hochzustufen (inkrementieren oder einfügen).Mongodb Upsert werfen DuplicateKeyException

[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 sollte mich nie wieder zurückkehren, diese Ausnahme. Habe ich recht?

+0

durch Zufall, zwei Upserts zur gleichen Zeit passiert? –

+0

Nein, ich serialisiere diese Upserts über eine Warteschlange. – biliboc

Antwort

16

Das Problem, das ich nur könnte folgende bin zu raten:

Sie tun Fund Operationen basierend auf vielen Kriterien. Das heißt, wenn es wegen eines Missverhältnisses eines Parameters (in Kriterien) fehlschlägt, wird es versuchen, das Dokument einzufügen.

So, die Chancen sind da, dass Sie versuchen, das gleiche Dokument mit derselben _id zu aktualisieren, aber einige der anderen Kriterien nicht übereinstimmen, was dazu führt, dass es erneut einfügen, die doppelte Schlüssel Ausnahme verursachen wird. Betrachten Sie das folgende Beispiel

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 }