View a markdown version of this page

Esecuzione di operazioni CRUD in Amazon DocumentDB con Java - Amazon DocumentDB

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Esecuzione di operazioni CRUD in Amazon DocumentDB con Java

Questa sezione illustra l'esecuzione delle operazioni CRUD (creazione, lettura, aggiornamento, eliminazione) in Amazon DocumentDB utilizzando i driver Java MongoDB.

Creazione e inserimento di documenti in una raccolta DocumentDB

L'inserimento di documenti in Amazon DocumentDB ti consente di aggiungere nuovi dati alle tue raccolte. Esistono diversi modi per eseguire gli inserimenti, a seconda delle esigenze e del volume di dati con cui stai lavorando. Il metodo più semplice per inserire un singolo documento nella raccolta è. insertOne() Per inserire più documenti contemporaneamente, è possibile utilizzare il insertMany() metodo, che consente di aggiungere una serie di documenti in un'unica operazione. Un altro metodo per inserire molti documenti in una raccolta DocumentDB è. bulkWrite() In questa guida, discutiamo tutti questi metodi per creare documenti in una raccolta DocumentDB.

insertOne()

Cominciamo esaminando come inserire un singolo documento in una raccolta Amazon DocumentDBB. L'inserimento di un singolo documento viene eseguito utilizzando il metodo. insertOne() Questo metodo richiede un metodo BsonDocument di inserimento e restituisce un InsertOneResult oggetto che può essere utilizzato per ottenere l'ID oggetto del nuovo documento inserito. Il codice di esempio seguente mostra l'inserimento di un documento relativo a un ristorante nella raccolta:

Document article = new Document() .append("restaurantId", "REST-21G145") .append("name", "Future-proofed Intelligent Bronze Hat") .append("cuisine", "International") .append("rating", new Document() .append("average", 1.8) .append("totalReviews", 267)) .append("features", Arrays.asList("Outdoor Seating", "Live Music")); try { InsertOneResult result = collection.insertOne(article); System.out.println("Inserted document with the following id: " + result.getInsertedId()); } catch (MongoWriteException e) { // Handle duplicate key or other write errors System.err.println("Failed to insert document: " + e.getMessage()); throw e; } catch (MongoException e) { // Handle other MongoDB errors System.err.println("MongoDB error: " + e.getMessage()); throw e; }

Durante l'utilizzoinsertOne(), assicuratevi di includere una gestione degli errori appropriata. Ad esempio, nel codice precedente, «restaurantId» ha un indice univoco e quindi eseguendo nuovamente questo codice si otterrà quanto segueMongoWriteException:

Failed to insert document: Write operation error on server docdbCluster.docdb.amazonaws.com:27017. Write error: WriteError{code=11000, message='E11000 duplicate key error collection: Restaurants index: restaurantId_1', details={}}.

insertMany ()

I metodi principali utilizzati per inserire molti documenti in una raccolta sono insertMany () e. bulkWrite()

Il insertMany() metodo è il modo più semplice per inserire più documenti in un'unica operazione. Accetta un elenco di documenti e li inserisce nella raccolta. Questo metodo è ideale quando si inserisce una serie di nuovi documenti indipendenti l'uno dall'altro e che non richiedono alcuna elaborazione speciale o operazioni miste. Il codice seguente mostra la lettura di documenti JSON da un file e il loro inserimento nella raccolta. La insertMany() funzione restituisce un InsertManyResult InsertManyResult oggetto che può essere utilizzato per ottenere gli ID di tutti i documenti inseriti.

// Read JSON file content String content = new String(Files.readAllBytes(Paths.get(jsonFileName))); JSONArray jsonArray = new JSONArray(content); // Convert JSON articles to Documents List < Document > restaurants = new ArrayList < > (); for (int i = 0; i < jsonArray.length(); i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); Document doc = Document.parse(jsonObject.toString()); restaurants.add(doc); } //insert documents in collection InsertManyResult result = collection.insertMany(restaurants); System.out.println("Count of inserted documents: " + result.getInsertedIds().size());

bulkWrite()

Il bulkWrite() metodo consente di eseguire più operazioni di scrittura (inserimento, aggiornamento, eliminazione) in un unico batch. È possibile utilizzarlo bulkWrite() quando è necessario eseguire diversi tipi di operazioni in un singolo batch, ad esempio inserire alcuni documenti e aggiornarne altri. bulkWrite()supporta due tipi di scrittura in batch, ordinata e non ordinata:

  • Operazioni ordinate: (impostazione predefinita) Amazon DocumentDB elabora le operazioni di scrittura in sequenza e si interrompe al primo errore riscontrato. Ciò è utile quando l'ordine delle operazioni è importante, ad esempio quando le operazioni successive dipendono da quelle precedenti. Tuttavia, le operazioni ordinate sono generalmente più lente delle operazioni non ordinate. Con le operazioni ordinate, è necessario risolvere il caso in cui il batch si interrompa al primo errore, lasciando potenzialmente alcune operazioni non elaborate.

  • Operazioni non ordinate: consente ad Amazon DocumentDB di elaborare gli inserimenti come un'unica esecuzione nel database. Se si verifica un errore con un documento, l'operazione continua con i documenti rimanenti. Ciò è particolarmente utile quando si inseriscono grandi quantità di dati e si possono tollerare alcuni errori, ad esempio durante la migrazione dei dati o le importazioni di massa in cui alcuni documenti potrebbero non riuscire a causa di chiavi duplicate. Nel caso di operazioni non ordinate, è necessario affrontare scenari di successo parziale in cui alcune operazioni hanno esito positivo mentre altre falliscono.

Quando si lavora con il bulkWrite() metodo, sono necessarie alcune classi essenziali. Innanzitutto, la WriteModel classe funge da classe base per tutte le operazioni di scrittura e con implementazioni specifiche come InsertOneModel, UpdateOneModel UpdateManyModel DeleteOneModel, e per la DeleteManyModel gestione di diversi tipi di operazioni.

La BulkWriteOptions classe è necessaria per configurare il comportamento delle operazioni in blocco, ad esempio impostare ordered/unordered l'esecuzione o bypassare la convalida dei documenti. La BulkWriteResult classe fornisce informazioni dettagliate sui risultati dell'esecuzione, incluso il numero di documenti inseriti, aggiornati ed eliminati.

Per la gestione degli errori, la MongoBulkWriteException classe è fondamentale in quanto contiene informazioni su eventuali errori durante l'operazione in blocco, mentre la BulkWriteError classe fornisce dettagli specifici sugli errori delle singole operazioni. Il codice seguente mostra un esempio di inserimento di un elenco di documenti, nonché di aggiornamento ed eliminazione di un singolo documento, il tutto nell'esecuzione di una singola chiamata al metodo. bulkWrite() Il codice mostra anche come utilizzare BulkWriteOptions e BulkWriteResult gestire correttamente gli errori dell'bulkWrite()operazione.

List < WriteModel < Document >> bulkOperations = new ArrayList < > (); // get list of 10 documents representing 10 restaurants List < Document > restaurantsToInsert = getSampleData(); for (Document doc: restaurantsToInsert) { bulkOperations.add(new InsertOneModel < > (doc)); } // Update operation bulkOperations.add(new UpdateOneModel < > ( new Document("restaurantId", "REST-Y2E9H5"), new Document("", new Document("stats.likes", 20)) .append("", new Document("rating.average", 4.5)))); // Delete operation bulkOperations.add(new DeleteOneModel < > (new Document("restaurantId", "REST-D2L431"))); // Perform bulkWrite operation try { BulkWriteOptions options = new BulkWriteOptions() .ordered(false); // Allow unordered inserts BulkWriteResult result = collection.bulkWrite(bulkOperations, options); System.out.println("Inserted: " + result.getInsertedCount()); System.out.println("Updated: " + result.getModifiedCount()); System.out.println("Deleted: " + result.getDeletedCount()); } catch (MongoBulkWriteException e) { System.err.println("Bulk write error occurred: " + e.getMessage()); // Log individual write errors for (BulkWriteError error: e.getWriteErrors()) { System.err.printf("Error at index %d: %s (Code: %d)%n", error.getIndex(), error.getMessage(), error.getCode()); // Log the problematic document Document errorDoc = new Document(error.getDetails()); if (errorDoc != null) { System.err.println("Problematic document: " + errorDoc); } } } catch (Exception e) { System.err.println("Error during bulkWrite: " + e.getMessage()); }

Retryable scrive

A differenza di MongoDB, Amazon DocumentDB non supporta scritture riutilizzabili. Di conseguenza, è necessario implementare una logica di riprova personalizzata nelle loro applicazioni, in particolare per gestire problemi di rete o indisponibilità temporanea del servizio. Una strategia di ripetizione ben implementata, in genere, comporta l'aumento del ritardo tra i tentativi e la limitazione del numero totale di tentativi. Gestione degli errori con logica di riprovaDi seguito è riportato un esempio di codice per la creazione di una logica di ripetizione con gestione degli errori.

Lettura e recupero di dati da una raccolta DocumentDB

L'interrogazione dei documenti in Amazon DocumentDB si basa su diversi componenti chiave che consentono di recuperare e manipolare i dati con precisione. Il find() metodo è l'API di interrogazione fondamentale nei driver Java di MongoDB. Consente il recupero di dati complessi con numerose opzioni per filtrare, ordinare e proiettare i risultati. Oltre al find() metodo, Filters FindIterable ci sono altri due componenti fondamentali che forniscono gli elementi costitutivi per le operazioni di interrogazione nei driver Java MongoDB.

La Filters classe è una classe di utilità nel driver Java MongoDB che fornisce un'API fluente per la creazione di filtri di interrogazione. Questa classe offre metodi di fabbrica statici che creano istanze di Bson oggetti che rappresentano varie condizioni di interrogazione. I metodi più comunemente usati includono eq() per i confronti di uguaglianza, gt() lt()gte(), e lte() per i confronti numerici e per la combinazione di più condizioni, and() or() per i test di appartenenza agli array in() e nin() per la corrispondenza dei modelli. regex() La classe è progettata per resistere ai tipi e fornisce un migliore controllo in fase di compilazione rispetto alle query non elaborate basate su documenti, rendendola l'approccio preferito per la creazione di query DocumentDB nelle applicazioni Java. La gestione degli errori è robusta, con chiare eccezioni generate per le costruzioni di filtri non valide.

FindIterableè un'interfaccia specializzata progettata per gestire il risultato del metodo. find() Fornisce un ricco set di metodi per perfezionare e controllare l'esecuzione delle query, offrendo un'API fluida per il concatenamento dei metodi. L'interfaccia include metodi essenziali di modifica delle query, ad esempio limit() per limitare il numero di documenti restituiti, per l'impaginazione, skip() per l'ordinamento dei risultati, sort() per la selezione di campi specifici e projection() per la selezione dell'indice. hint() Le operazioni batch, skip e limit in FindIterable sono strumenti essenziali di impaginazione e gestione dei dati che aiutano a controllare il modo in cui i documenti vengono recuperati ed elaborati dal database.

Batching (batchSize) controlla quanti documenti DocumentDB restituisce al client in un singolo round trip di rete. Quando si imposta una dimensione del batch, DocumentDB non restituisce tutti i documenti corrispondenti contemporaneamente, ma li restituisce in gruppi della dimensione batch specificata.

Skip consente di compensare il punto di partenza dei risultati, dicendo essenzialmente a DocumentDB di saltare un numero specificato di documenti prima di iniziare a restituire le corrispondenze. Ad esempio, skip(20) ignorerà i primi 20 documenti corrispondenti. Questo è comunemente usato negli scenari di impaginazione in cui si desidera recuperare pagine successive di risultati.

Limite limita il numero totale di documenti che possono essere restituiti da una query. Quando lo specifichilimit(n), DocumentDB interromperà la restituzione di documenti dopo aver restituito «n» documenti, anche se ci sono più corrispondenze nel database.

FindIterablesupporta sia gli iteratori che i modelli di cursore durante il recupero di documenti da Amazon DocumentDB. Il vantaggio dell'utilizzo FindIterable come iteratore è che consente il caricamento lento dei documenti e recupera i documenti solo quando richiesto dall'applicazione. Un altro vantaggio dell'utilizzo di iterator è che non sei responsabile del mantenimento della connessione al cluster e quindi non è richiesta una chiusura esplicita della connessione.

FindIterableforniscono anche un supporto MongoCursor che consente di utilizzare i pattern dei cursori quando si lavora con le query di Amazon DocumentDB. MongoCursorè un'implementazione specifica del driver Java di MongoDB che fornisce il controllo sulle operazioni del database e sulla gestione delle risorse. Implementa l'AutoCloseableinterfaccia, consentendo una gestione esplicita delle risorse tramite blocchi try-with-resources, fondamentale per chiudere correttamente le connessioni al database e liberare le risorse del server. Per impostazione predefinita, il cursore scade dopo 10 minuti e DocumentDB non offre la possibilità di modificare questo comportamento di timeout. Quando lavori con dati in batch, assicurati di recuperare il batch di dati successivo prima che scada il timeout del cursore. Una considerazione fondamentale nell'utilizzo MongoCursor è che richiede una chiusura esplicita per evitare perdite di risorse.

In questa sezione, vengono presentati diversi esempi perfind(), eFilters. FindIterable

Il seguente esempio di codice mostra come utilizzare per find() recuperare un singolo documento utilizzando il relativo campo «restaurantID»:

Document filter = new Document("restaurantId", "REST-21G145"); Document result = collection.find(filter).first();

Sebbene l'utilizzo Filters consenta un migliore controllo degli errori in fase di compilazione, il driver java consente anche di specificare un Bson filtro direttamente nel metodo. find() Il codice di esempio seguente passa il Bson documento afind():

result = collection.find(new Document("$and", Arrays.asList( new Document("rating.totalReviews", new Document("$gt", 1000)), new Document("priceRange", "$$"))))

Il codice di esempio successivo mostra diversi esempi di utilizzo della Filters classe confind():

FindIterable < Document > results; // Exact match results = collection.find(Filters.eq("name", "Thai Curry Palace")); // Not equal results = collection.find(Filters.ne("cuisine", "Thai")); // find an element in an array results = collection.find(Filters.in("features", Arrays.asList("Private Dining"))); // Greater than results = collection.find(Filters.gt("rating.average", 3.5)); // Between (inclusive) results = collection.find(Filters.and( Filters.gte("rating.totalReviews", 100), Filters.lte("rating.totalReviews", 200))); // AND results = collection.find(Filters.and( Filters.eq("cuisine", "Thai"), Filters.gt("rating.average", 4.5))); // OR results = collection.find(Filters.or( Filters.eq("cuisine", "Thai"), Filters.eq("cuisine", "American"))); // All document where the Field exists results = collection.find(Filters.exists("michelin")); // Regex results = collection.find(Filters.regex("name", Pattern.compile("Curry", Pattern.CASE_INSENSITIVE))); // Find all document where the array contain the list of value regardless of its order results = collection.find(Filters.all("features", Arrays.asList("Private Dining", "Parking"))); // Array size results = collection.find(Filters.size("features", 4));

L'esempio seguente mostra come concatenare le operazioni di sort()skip(),limit(), e batchSize() su un FindIterable oggetto. L'ordine in cui vengono fornite queste operazioni influirà sulle prestazioni della query. Come procedura consigliata, l'ordine di queste operazioni dovrebbe essere sort()projection(),skip(), limit() ebatchSize().

FindIterable < Document > results = collection.find(Filters.gt("rating.totalReviews", 1000)) // Sorting .sort(Sorts.orderBy( Sorts.descending("address.city"), Sorts.ascending("cuisine"))) // Field selection .projection(Projections.fields( Projections.include("name", "cuisine", "priceRange"), Projections.excludeId())) // Pagination .skip(20) .limit(10) .batchSize(2);

Il codice di esempio seguente mostra la creazione di un iteratore suFindIterable. Utilizza il forEach costrutto di Java per attraversare il set di risultati.

collection.find(Filters.eq("cuisine", "American")).forEach(doc -> System.out.println(doc.toJson()));

Nell'ultimo esempio di find() codice, mostra come utilizzare cursor() per il recupero dei documenti. Crea il cursore nel blocco try che assicura che il cursore venga chiuso quando il codice esce dal blocco try.

try (MongoCursor < Document > cursor = collection.find(Filters.eq("cuisine", "American")) .batchSize(25) .cursor()) { while (cursor.hasNext()) { Document doc = cursor.next(); System.out.println(doc.toJson()); } } // Cursor automatically closed

Aggiornamento dei documenti esistenti in una raccolta DocumentDB

Amazon DocumentDB offre meccanismi flessibili e potenti per modificare i documenti esistenti e inserirne di nuovi quando non esistono. Il driver Java MongoDB offre diversi metodi per gli aggiornamenti: per l'aggiornamento di singoli documenti, updateOne() per l'aggiornamento di più documenti e updateMany() replaceOne() per la sostituzione completa dei documenti. Oltre a questi tre metodi, Updates UpdateOptions, UpdateResult ci sono altri componenti fondamentali che forniscono gli elementi costitutivi per le operazioni di aggiornamento nei driver Java MongoDB.

La Updates classe nel driver Java MongoDB è una classe di utilità che fornisce metodi di fabbrica statici per la creazione di operatori di aggiornamento. Serve come generatore principale per la creazione di operazioni di aggiornamento in modo leggibile e sicuro per i tipi. Metodi di base come set()unset(), e inc() consentono la modifica diretta dei documenti. La potenza di questa classe diventa evidente quando si combinano più operazioni utilizzando il Updates.combine() metodo che consente di eseguire più operazioni di aggiornamento in modo atomico, garantendo la coerenza dei dati.

UpdateOptionsè una potente classe di configurazione nel driver Java di MongoDB che fornisce funzionalità di personalizzazione essenziali per le operazioni di aggiornamento dei documenti. Due aspetti importanti di questa classe sono il supporto per upsert e array filter per le operazioni di aggiornamento. La funzionalità upsert, abilitata tramiteupsert(true), consente la creazione di nuovi documenti quando non viene trovato alcun documento corrispondente durante un'operazione di aggiornamento. TramitearrayFilters(), l'operazione di aggiornamento può aggiornare con precisione gli elementi dell'array che soddisfano criteri specifici.

UpdateResultnel driver Java di MongoDB fornisce il meccanismo di feedback che descrive in dettaglio l'esito di un'operazione di aggiornamento. Questa classe racchiude tre metriche chiave: il numero di documenti che corrispondono ai criteri di aggiornamento (matchedCount), il numero di documenti effettivamente modificati () e le informazioni su eventuali documenti modificati (modifiedCount). upsertedId La comprensione di queste metriche è essenziale per una corretta gestione degli errori, la verifica delle operazioni di aggiornamento e il mantenimento della coerenza dei dati nelle applicazioni.

Aggiorna e sostituisci un singolo documento

In DocumentDB, l'aggiornamento di un singolo documento può essere eseguito utilizzando il metodo updateOne (). Questo metodo utilizza un parametro di filtro, in genere fornito dalla Filters classe, per identificare il documento da aggiornare, un parametro Updat e che determina i campi da aggiornare e un UpdateOptions parametro opzionale per impostare diverse opzioni per l'aggiornamento. L'utilizzo del updateOne() metodo aggiornerà solo il primo documento che corrisponde ai criteri di selezione. Il codice di esempio seguente aggiorna un singolo campo di un documento:

collection.updateOne(Filters.eq("restaurantId", "REST-Y2E9H5"), Updates.set("name", "Amazing Japanese sushi"));

Per aggiornare più campi in un documento, utilizzare updateOne() with Update.combine() come mostrato nell'esempio seguente. Questo esempio mostra anche come aggiungere un elemento a un array nel documento.

List<Bson> updates = new ArrayList<>(); // Basic field updates updates.add(Updates.set("name", "Shanghai Best")); // Array operations updates.add(Updates.addEachToSet("features", Arrays.asList("Live Music"))); // Counter updates updates.add(Updates.inc("rating.totalReviews", 10)); // Combine all updates Bson combinedUpdates = Updates.combine(updates); // Execute automic update with one call collection.updateOne(Filters.eq("restaurantId","REST-1J83NH"), combinedUpdates);

L'esempio di codice seguente dimostra come aggiornare un documento nel database. Se il documento specificato non esiste, l'operazione lo inserirà automaticamente come nuovo documento. Questo codice mostra anche come utilizzare le metriche disponibili tramite l'UpdateResultoggetto.

Bson filter = Filters.eq("restaurantId", "REST-0Y9GL0"); Bson update = Updates.set("cuisine", "Indian"); // Upsert operation UpdateOptions options = new UpdateOptions().upsert(true); UpdateResult result = collection.updateOne(filter, update, options); if (result.getUpsertedId() != null) { System.out.println("Inserted document with _id: " + result.getUpsertedId()); } else { System.out.println("Updated " + result.getModifiedCount() + " document(s)"); }

L'esempio di codice seguente dimostra come sostituire completamente un documento esistente con un nuovo documento utilizzando il replaceOne() metodo, anziché aggiornare i singoli campi. Il replaceOne() metodo sovrascrive l'intero documento, preservando solo il _id campo dell'originale. Se più documenti soddisfano i criteri del filtro, viene sostituito solo il primo documento rilevato.

Document newDocument = new Document() .append("restaurantId", "REST-0Y9GL0") .append("name", "Bhiryani Adda") .append("cuisine", "Indian") .append("rating", new Document() .append("average", 4.8) .append("totalReviews", 267)) .append("features", Arrays.asList("Outdoor Seating", "Live Music")); UpdateResult result = collection.replaceOne( Filters.eq("restaurantId", "REST-0Y9GL0"), newDocument); System.out.printf("Modified %d document%n", result.getModifiedCount());

Aggiornare più documenti

Esistono due modi per aggiornare più documenti in una raccolta contemporaneamente. È possibile utilizzare il updateMany() metodo o utilizzare il metodo UpdateManyModel con il bulkWrite() metodo. Il updateMany() metodo utilizza un parametro di filtro per selezionare i documenti da aggiornare, il Update parametro per identificare i campi da aggiornare e un UpdateOptions parametro opzionale per specificare le opzioni di aggiornamento.

Il codice di esempio seguente dimostra l'utilizzo del updateMany() metodo:

Bson filter = Filters.and( Filters.in("features", Arrays.asList("Private Dining")), Filters.eq("cuisine", "Thai")); UpdateResult result1 = collection.updateMany(filter, Updates.set("priceRange", "$$$"));

Il codice di esempio seguente illustra il bulkWrite() metodo che utilizza lo stesso aggiornamento:

BulkWriteOptions options = new BulkWriteOptions().ordered(false); List < WriteModel < Document >> updates = new ArrayList < > (); Bson filter = Filters.and( Filters.in("features", Arrays.asList("Private Dining")), Filters.eq("cuisine", "Indian")); Bson updateField = Updates.set("priceRange", "$$$"); updates.add(new UpdateManyModel < > (filter, updateField)); BulkWriteResult result = collection.bulkWrite(updates, options); System.out.printf("Modified %d document%n", result.getModifiedCount());

Rimozione di documenti da una raccolta DocumentDB

Il driver Java MongoDB consente deleteOne() di rimuovere un singolo documento e deleteMany() di rimuovere più documenti che corrispondono a criteri specifici. Proprio come l'aggiornamento, anche l'operazione di eliminazione può essere utilizzata con il bulkWrite() metodo. Entrambi deleteOne() deleteMany() restituiscono un DeleteResult oggetto che fornisce informazioni sull'esito dell'operazione, incluso il conteggio dei documenti eliminati. Di seguito è riportato un esempio di utilizzo deleteMany() per rimuovere più documenti:

Bson filter = Filters.and( Filters.eq("cuisine", "Thai"), Filters.lt("rating.totalReviews", 50)); DeleteResult result = collection.deleteMany(filter); System.out.printf("Deleted %d document%n", result.getDeletedCount());

Gestione degli errori con logica di riprova

Una solida strategia di gestione degli errori per Amazon DocumentDB dovrebbe implementare la categorizzazione degli errori in ripetibili (come timeout di rete, problemi di connessione) e non ripetibili (come errori di autenticazione, query non valide). In caso di errori operativi dovuti a errori che devono essere ripetuti, dovrebbe implementare un ritardo tra ogni tentativo e il numero massimo di tentativi di ripetizione. Le operazioni CRUD dovrebbero trovarsi in un blocco try-catch contenente catches e le relative sottoclassi. MongoException Inoltre, dovrebbe includere il monitoraggio e la registrazione degli errori per la visibilità operativa. Di seguito è riportato un esempio di codice che mostra come implementare la gestione degli errori relativi ai nuovi tentativi:

int MAX_RETRIES = 3; int INITIAL_DELAY_MS = 1000; int retryCount = 0; while (true) { try { crud_operation(); //perform crud that will throw MongoException or one of its subclass break; } catch (MongoException e) { if (retryCount < MAX_RETRIES) { retryCount++; long delayMs = INITIAL_DELAY_MS * (long) Math.pow(2, retryCount - 1); try { TimeUnit.MILLISECONDS.sleep(delayMs); } catch (InterruptedException t) { Thread.currentThread().interrupt(); throw new RuntimeException("Retry interrupted", t); } continue; } else throw new RuntimeException("Crud operation failed", e); } }