J'utilise Cloud Firestore et j'ai une collection de documents. Pour chaque document de la collection, je voudrais mettre à jour l'un des champs.
L'utilisation d'une transaction pour effectuer la mise à jour serait inefficace car je n'ai pas besoin de lire les données lors de la mise à jour.
Les mises à jour par lots semblent être la bonne direction, mais les documents n'incluent pas d'exemples de mise à jour de plusieurs documents à la fois. Voir ici: Ecritures par lots
Si vous avez utilisé la base de données Firebase, il n'était pas possible d'écrire sur des emplacements séparés complètement uniques, c'est pourquoi vous devez utiliser des écritures par lots, ce qui signifie que toutes les opérations réussissent ou qu'aucune d'entre elles n'est appliquée.
Concernant Firestore, toutes les opérations sont désormais traitées atomiquement. Cependant, vous pouvez exécuter plusieurs opérations d'écriture en tant que lot unique contenant toute combinaison d'opérations set (), update () ou delete (). Un lot d'écritures se termine de manière atomique et peut écrire sur plusieurs documents.
Il s'agit d'un exemple simple concernant une opération par lots pour une opération d'écriture, de mise à jour et de suppression.
WriteBatch batch = db.batch();
DocumentReference johnRef = db.collection("users").document("John");
batch.set(johnRef, new User());
DocumentReference maryRef = db.collection("users").document("Mary");
batch.update(maryRef, "Anna", 20); //Update name and age
DocumentReference alexRef = db.collection("users").document("Alex");
batch.delete(alexRef);
batch.commit().addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
// ...
}
});
L'appel de la méthode commit()
sur l'objet batch signifie que vous validez l'intégralité du batch.
Je cherchais une solution, je n'en ai trouvé aucune, alors j'ai fait celle-ci, si quelqu'un est intéressé.
public boolean bulkUpdate() {
try {
// see https://firebase.google.com/docs/firestore/quotas#writes_and_transactions
int writeBatchLimit = 500;
int totalUpdates = 0;
while (totalUpdates % writeBatchLimit == 0) {
WriteBatch writeBatch = this.firestoreDB.batch();
List<QueryDocumentSnapshot> documentsInBatch =
this.firestoreDB.collection("animals")
.whereEqualTo("species", "cat")
.limit(writeBatchLimit)
.get()
.get()
.getDocuments();
if (documentsInBatch.isEmpty()) {
break;
}
documentsInBatch.forEach(
document -> writeBatch.update(document.getReference(), "hasTail", true));
writeBatch.commit().get();
totalUpdates += documentsInBatch.size();
}
System.out.println("Number of updates: " + totalUpdates);
} catch (Exception e) {
return false;
}
return true;
}