2011-09-13 4 views
4

Je souhaite mettre à jour plusieurs lignes dans Ma collection, appelées "Utilisateurs". En ce moment je suis mise à jour séparément les deux rangées mais je veux faire la même chose dans une requête.Mettre à jour plusieurs lignes dans MongoDB Java Driver

Mon code actuel:

coll.update(new BasicDBObject().append("key", k1), new BasicDBObject().append("$inc", new BasicDBObject().append("balance", 10)));    
coll.update(new BasicDBObject().append("key", k2), new BasicDBObject().append("$inc", new BasicDBObject().append("balance", -10))); 

Comment faire ces deux mises à jour séparées dans une déclaration?

Répondre

3

Tout d'abord laissez-moi traduis votre code java script shell afin que les gens puissent le lire:

db.coll.update({key: k1}, {$inc:{balance:10}}) 
db.coll.update({key: k2}, {$inc:{balance:-10}}) 

Maintenant, la raison pour laquelle vous ne serez jamais en mesure de le faire dans une mise à jour est parce qu'il n'y a aucun moyen de fournir une clause de mise à jour unique par document correspondant. Vous pouvez VRAC vos mises à jour afin que vous puissiez le faire (pseudoish):

set1 = getAllKeysForBalanceIncrease(); 
set2 = getAllKeysForBalanceDecrease(); 

db.coll.update({key:{$in:set1}}, {$inc:{balance:10}}, false, true) 
db.coll.update({key:{$in:set2}}, {$inc:{balance:-10}}, false, true) 

En d'autres termes, vous pouvez mettre à jour plusieurs documents dans l'écriture atomique, mais l'opération de mise à jour sera statique pour tous les documents. Donc, l'agrégation de tous les documents qui nécessitent la même mise à jour est votre seul chemin d'optimisation.

L'$ à la clause peut être composé en Java par:

ObjectId[] oidArray = getAllKeysEtc(); 
query = new BasicDBObject("key", new BasicDBObject("$in", oidArray)); 
-1

Dans MongoDB, vous ne disposez pas de transactions couvrant plusieurs documents. Seules les écritures sur un document sont atomiques. Mais vous pouvez faire des mises à jour avec:

public WriteResult update(DBObject q, 
         DBObject o, 
         boolean upsert, 
         boolean multi) 

Mais attention, ce ne sera pas dans une transaction.

+0

Qu'est-ce qui ne va pas dans cette réponse? Ce qu'il demande n'est pas possible. – hellectronic

+0

(je n'ai pas downvote, mais si je devais deviner--) réduire le temps passé dans une transaction est certainement une raison pour envoyer des mises à jour dans un lot. Mais une autre raison est d'augmenter le débit. Premièrement, les lots permettent l'amortissement des frais généraux sur le nombre d'enregistrements dans le lot. Deuxièmement, si le pilote avec lequel vous travaillez n'est pas asynchrone, le traitement par lots évite le coût de la latence d'attente d'un ACK pour chaque mise à jour. –

Questions connexes