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 descrive l'esecuzione dell'operazione 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()

Iniziamo 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 BsonDocumentper l'inserimento e restituisce un InsertOneResultoggetto che può essere utilizzato per ottenere l'id dell'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 genererà 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 un batch 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 InsertManyResultInsertManyResultoggetto che può essere utilizzato per ottenere tutti IDs 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 unico 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 inserti 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 può 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 successo mentre altre falliscono.

Quando si utilizza il bulkWrite() metodo, sono necessarie alcune classi essenziali. Innanzitutto, la WriteModelclasse funge da classe base per tutte le operazioni di scrittura e con implementazioni specifiche come InsertOneModel,, UpdateOneModelUpdateManyModelDeleteOneModel, e la DeleteManyModelgestione di diversi tipi di operazioni.

La BulkWriteOptionsclasse è necessaria per configurare il comportamento delle operazioni di massa, come impostare l' ordered/unordered esecuzione o ignorare la convalida dei documenti. La BulkWriteResultclasse fornisce informazioni dettagliate sui risultati dell'esecuzione, incluso il conteggio dei documenti inseriti, aggiornati ed eliminati.

Per la gestione degli errori, la MongoBulkWriteExceptionclasse è fondamentale in quanto contiene informazioni su eventuali errori durante l'operazione in blocco, mentre la BulkWriteErrorclasse 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'ambito dell'esecuzione di una singola chiamata al metodo. bulkWrite() Il codice mostra anche come utilizzare BulkWriteOptionse BulkWriteResultgestire 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()); }

Riprova le scritture

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

Lettura e recupero di dati da una raccolta DocumentDB

L'interrogazione di documenti in Amazon DocumentDB ruota attorno a diversi componenti chiave che consentono di recuperare e manipolare i dati con precisione. Il find()metodo è l'interrogazione fondamentale APIs nei driver Java MongoDB. Consente il recupero di dati complessi con numerose opzioni per il filtraggio, l'ordinamento e la proiezione dei risultati. Oltre al find() metodo, Filterse FindIterablesono 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 fluida per la creazione di filtri di query. Questa classe offre metodi di fabbrica statici che creano istanze di Bson oggetti che rappresentano varie condizioni di query. 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 essere sicura dai tipi e offre 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 è solida, con chiare eccezioni 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, come limit() la limitazione del numero di documenti restituiti, l'impaginazione, skip() l'ordinamento dei risultati, sort() la selezione di campi specifici e projection() la selezione dell'indice. hint() Le operazioni batch, skip e limit di 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 invece in gruppi della dimensione del batch specificata.

Skip consente di compensare il punto di partenza dei risultati, essenzialmente dicendo a DocumentDB di ignorare un determinato numero 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.

Il limite limita il numero totale di documenti che possono essere restituiti da una query. Quando si specificalimit(n), DocumentDB smetterà di restituire documenti dopo aver restituito 'n' documenti, anche se ci sono più corrispondenze nel database.

FindIterablesupporta modelli di iteratori e cursori durante il recupero di documenti da Amazon DocumentDB. Il vantaggio dell'utilizzo FindIterable di un 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 la chiusura esplicita della connessione.

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

In questa sezione, vengono presentati diversi esempi difind(), Filters e. FindIterable

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

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

Anche se l'utilizzo Filters consente un migliore controllo degli errori in fase di compilazione, il driver java consente anche di specificare un Bson filtro direttamente nel metodo. find() Il seguente codice di esempio 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 ottimale, 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 esplorare 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 utilizzarlo cursor() per il recupero dei documenti. Crea il cursore nel blocco try che assicura che il cursore si chiuda 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 di 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 aggiornamentiupdateOne(): per l'aggiornamento di singoli documentiupdateMany(), per l'aggiornamento di più documenti replaceOne() e per la sostituzione completa dei documenti. Oltre a questi tre metodi, UpdatesUpdateOptions, e UpdateResultci sono altri componenti fondamentali che forniscono gli elementi costitutivi per le operazioni di aggiornamento nei driver Java MongoDB.

La Updates classe del driver Java MongoDB è una classe di utilità che fornisce metodi di fabbrica statici per la creazione di operatori di aggiornamento. Funge da generatore principale per la creazione di operazioni di aggiornamento in modo leggibile e sicuro dai tipi. Metodi di base come set() e inc() consentono unset() 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 atomicamente, 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 dei filtri upsert e array per le operazioni di aggiornamento. La funzione upsert, abilitata tramiteupsert(true), consente la creazione di nuovi documenti quando non vengono trovati documenti corrispondenti 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 incapsula tre metriche chiave: il numero di documenti corrispondenti ai criteri di aggiornamento (matchedCount), il numero di documenti effettivamente modificati () e le informazioni su eventuali documenti alterati (modifiedCount). upsertedId La comprensione di queste metriche è essenziale per la 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, solitamente fornito dalla Filters classe, per identificare il documento da aggiornare, un parametro Updat e che determina quali campi 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, utilizzate updateOne() with Update.combine() come illustrato nell'esempio seguente. Questo esempio mostra anche come aggiungere un elemento a una matrice 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);

Il seguente esempio di codice mostra 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)"); }

Il seguente esempio di codice 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 di 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());

Aggiorna più documenti

Esistono due modi per aggiornare più documenti in una raccolta contemporaneamente. È possibile utilizzare il updateMany() metodo o utilizzare il UpdateManyModelcon 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 illustra 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 mostra il bulkWrite() metodo utilizzando 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());

Rimuovere documenti da una raccolta DocumentDB

Il driver Java MongoDB deleteOne() consente di rimuovere un singolo documento deleteMany() e di rimuovere più documenti che soddisfano criteri specifici. Proprio come l'aggiornamento, anche l'operazione di eliminazione può essere utilizzata con il bulkWrite() metodo. Entrambi deleteOne() deleteMany() restituiscono un DeleteResultoggetto che fornisce informazioni sull'esito dell'operazione, incluso il numero di 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 la logica di ripetizione

Una solida strategia di gestione degli errori per Amazon DocumentDB dovrebbe implementare la classificazione degli errori in riprovabili (come timeout di rete, problemi di connessione) e non riprovabili (come errori di autenticazione, query non valide). In caso di errori operativi dovuti a errori che devono essere ritentati, dovrebbe prevedere un intervallo di tempo tra ogni tentativo e il numero massimo di tentativi. Le operazioni CRUD dovrebbero trovarsi in un blocco try-catch che cattura MongoExceptione le sue sottoclassi. Inoltre, dovrebbe includere il monitoraggio e la registrazione degli errori per la visibilità operativa. Di seguito è riportato un codice di esempio che mostra come implementare la gestione degli errori tra 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); } }