

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à.

# Guida alla programmazione Java di Amazon DocumentDB
<a name="docdb-java-pg"></a>

Questa guida completa fornisce una guida dettagliata per lavorare con Amazon DocumentDB utilizzando i driver Java di MongoDB, coprendo gli aspetti essenziali delle operazioni e della gestione dei database.

**Topics**
+ [

## Introduzione
](#java-pg-intro)
+ [

## Prerequisiti
](#java-pg-prereqs)
+ [Modelli di dati](#java-pg-data-models)
+ [Connessione con un driver Java](java-pg-connect-mongo-driver.md)
+ [Operazioni CRUD con Java](java-crud-operations.md)
+ [Gestione degli indici con Java](index-management-java.md)
+ [Programmazione basata sugli eventi](event-driven-programming.md)

## Introduzione
<a name="java-pg-intro"></a>

La guida inizia con la connettività, spiegando come stabilire connessioni sicure ai cluster DocumentDB utilizzando il driver Java MongoDB. Descrive in dettaglio i componenti della stringa di connessione, SSL/TLS l'implementazione e le varie opzioni di connessione, tra cui l'autenticazione IAM e il pool di connessioni, oltre a solide strategie di gestione degli errori.

Nella sezione sulle operazioni CRUD (create, read, update, delete), la guida tratta in modo approfondito la manipolazione dei documenti, dimostrando come creare, leggere, aggiornare ed eliminare documenti utilizzando operazioni singole e in blocco. Spiega l'uso di filtri, interrogazioni e varie opzioni operative, enfatizzando al contempo le migliori pratiche per la gestione degli errori e l'implementazione della logica dei tentativi per una maggiore affidabilità. La guida tratta ampiamente anche la gestione degli indici, descrivendo in dettaglio la creazione e la manutenzione di diversi tipi di indici, tra cui indici a campo singolo, composti, sparsi e di testo. Spiega come ottimizzare le prestazioni delle query attraverso la corretta selezione degli indici e l'utilizzo della funzione per analizzare i piani di esecuzione delle `explain()` query.

L'ultima sezione si concentra sulla programmazione basata sugli eventi utilizzando i flussi di modifica di Amazon DocumentDB, dimostrando come implementare il monitoraggio delle modifiche dei dati in tempo reale nelle applicazioni Java. Copre l'implementazione dei cursori Change Stream, la gestione dei token di curriculum per il funzionamento continuo e le operazioni basate sul tempo per l'elaborazione dei dati storici. In tutta la guida vengono forniti esempi pratici di codice e best practice, che la rendono una risorsa inestimabile per la creazione di applicazioni Java affidabili con Amazon DocumentDB.

## Prerequisiti
<a name="java-pg-prereqs"></a>

Prima di iniziare, assicurati di disporre di:
+ Un AWS account con un cluster DocumentDB configurato. Vedi questo [post di blog introduttivo](https://aws.amazon.com/blogs/database/part-1-getting-started-with-amazon-documentdb-using-amazon-ec2/) sulla configurazione del cluster DocumentDB.
+ Java Development Kit (JDK) installato (per questa guida utilizzeremo Amazon [Corretto 21](https://docs.aws.amazon.com/corretto/latest/corretto-21-ug/downloads-list.html)).
+ Maven per la gestione delle dipendenze.

## Modelli di dati per questa guida
<a name="java-pg-data-models"></a>

Tutto il codice di esempio in questa guida presuppone una connessione a un database di test «ProgGuideData» che contiene una raccolta «Ristoranti». Tutti i codici di esempio di questa guida funzionano su un sistema di elenchi di ristoranti e di seguito è riportato un esempio di come appare un documento in questo sistema:

```
{
    "_id": "ab6ad8f119b5bca3efa2c7ae",
    "restaurantId": "REST-CRT9BL",
    "name": "Thai Curry Palace",
    "description": "Amazing Restaurant, must visit",
    "cuisine": "Thai",
    "address": {
        "street": "914 Park Street",
        "city": "Bryan",
        "state": "AL",
        "zipCode": "96865",
        "location": {
            "type": "Point",
            "coordinates": [-25.4619, 8.389]
        }
    },
    "contact": {
        "phone": "(669) 915-9056 x6657"
    },
    "rating": {
        "average": 3.4,
        "totalReviews": 275
    },
    "priceRange": "$",
    "menu": [{
        "category": "Appetizers",
        "items": [{
            "name": "Buffalo Chicken Wings",
            "price": 13.42
        }]
    }],
    "features": [
        "Private Dining"
    ],
    "isActive": false“ michelin”: {“
        star”: 3,
        “ranking_years”: 4
    }
}
```

Tutti gli esempi di codice che mostrano CRUD, la gestione degli indici e la programmazione basata sugli eventi presuppongono la presenza di un [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoClient.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoClient.html)oggetto`dbClient`, un oggetto e un [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoDatabase.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoDatabase.html)oggetto`connectionDB`. [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoCollection.html#find()](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoCollection.html#find())`collection`

**Nota**  
Tutti gli esempi di codice in questa guida sono stati testati con il driver Java MongoDB versione 5.3.0.

# Connessione ad Amazon DocumentDB con un driver Java MongoDB
<a name="java-pg-connect-mongo-driver"></a>

Questa sezione fornisce una step-by-step guida per la connessione ad Amazon DocumentDB utilizzando i driver Java. Questo ti consentirà di iniziare a integrare DocumentDB nelle tue applicazioni Java.

**Topics**
+ [

## Fase 1: Configurazione del progetto
](#step1-set-up)
+ [

## Passaggio 2: creare la stringa di connessione
](#step2-create-connection-string)
+ [

## Fase 3: Scrivere il codice di connessione
](#step3-write-connect-code)
+ [

## Fase 4: Gestire le eccezioni di connessione
](#step4-handle-connect-exceptions)
+ [

## Fase 5: Esecuzione del codice
](#step5-running-code)
+ [

## Le migliori pratiche di connessione
](#java-connect-best-practices)

## Fase 1: Configurazione del progetto
<a name="step1-set-up"></a>

1. Usando Maven, crea un progetto java:

   ```
   mvn archetype:generate -DgroupId=com.docdb.guide -DartifactId=my-docdb-project -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
   ```

1. Aggiungi il driver Java MongoDB come dipendenza per il progetto nel tuo file 'pom.xml':

   ```
   <dependency>
       <groupId>org.mongodb</groupId>
       <artifactId>mongodb-driver-sync</artifactId> 
       <version>5.3.0</version> 
   </dependency>
   ```

## Passaggio 2: creare la stringa di connessione
<a name="step2-create-connection-string"></a>

La stringa di connessione di Amazon DocumentDB è essenziale per stabilire una connessione tra l'applicazione e il cluster DocumentDB. Questa stringa incapsula informazioni cruciali come l'endpoint del cluster, la porta, i dettagli di autenticazione e varie opzioni di connessione. Per creare una stringa di connessione DocumentDB, in genere si inizia con il formato base:

```
"mongodb://username:password@cluster-endpoint:port/?[connection options]"
```

Dovrai sostituire «nome utente» e «password» con le tue credenziali effettive. Puoi trovare l'endpoint e il numero di porta del tuo cluster Console di gestione AWS sia in che tramite. AWS CLI Vedi [Individuazione degli endpoint di un cluster](db-cluster-endpoints-find.md) per trovare l'endpoint del cluster per il tuo cluster. La porta predefinita per DocumentDB è 27017.

**Esempi di stringhe di connessione**
+ Effettuare una connessione a DocumentDB utilizzando la crittografia in transito e assicurandosi che le richieste di lettura vadano alle repliche di lettura e scrivano al file primario:

  ```
  "mongodb://username:password@cluster-endpoint:27017/?tls=true& 
     tlsCAFile=global-bundle.pem& 
     readPreference=secondaryPreferred&
     retryWrites=false"
  ```
+ Effettuare una connessione a DocumentDB utilizzando l'autenticazione IAM:

  ```
  "mongodb://cluster-endpoint:27017/?tls=true& 
     tlsCAFile=global-bundle.pem& 
     readPreference=secondaryPreferred&
     retryWrites=false&
     authSource=%24external&
     authMechanism=MONGODB-AWS"
  ```

Le diverse opzioni disponibili per la stringa di connessione sono le seguenti:
+ [Certificato TLS](#connection-string-tls)
+ [Lettura da repliche lette](#connection-string-read-rep)
+ [Scrivi preoccupazioni e scrivi un diario](#connection-string-write-journal)
+ [RetryWrites](#connection-string-retry-writes)
+ [Autenticazione IAM](#connection-string-iam-auth)
+ [Pool di connessioni](#connection-string-pool)
+ [Parametri di timeout della connessione](#connection-string-timeout)

### Certificato TLS
<a name="connection-string-tls"></a>

**`tls=true|false`**— Questa opzione abilita o disabilita Transport Layer Security (TLS). Per impostazione predefinita, la crittografia in transito è abilitata sul cluster Amazon DocumentDB e pertanto, a meno che TLS non sia disabilitato a livello di cluster, il valore per questa opzione dovrebbe essere. `true`

Quando si utilizza TLS, il codice deve fornire un certificato SSL durante la creazione della connessione a un cluster DocumentDB. Scarica il certificato necessario per stabilire la connessione sicura al cluster:. [https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem](https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem) Esistono due modi per utilizzare il `global-bundle.pem` file.
+ **Opzione 1**: estrai tutti i certificati dal `global-bundle.pem` file e utilizza il keytool di Java per archiviarli in un `.jks` file che può essere successivamente utilizzato nel codice. Fate riferimento alla scheda Java [Connessione con TLS abilitato](connect_programmatically.md#connect_programmatically-tls_enabled) per lo script che mostra come eseguire questa operazione.
+ **Opzione 2**: aggiungi dinamicamente il `global-bundle.pem` file nel codice, crea un keystore in memoria e utilizzalo `SSLContext` per fornire il certificato come parte della connessione.

### Lettura da repliche lette
<a name="connection-string-read-rep"></a>

**`replicaSet=rs0&readPreference=secondaryPreferred`**— La specificazione di queste due opzioni indirizza tutte le richieste di lettura alle repliche di lettura e le richieste di scrittura all'istanza principale. L'utilizzo `replicaSet=rs0` nella stringa di connessione consente al driver MongoDB di mantenere una visualizzazione aggiornata automaticamente della topologia del cluster, consentendo alle applicazioni di mantenere la visibilità delle configurazioni correnti dei nodi man mano che le istanze vengono aggiunte o rimosse. La mancata fornitura di queste opzioni o la mancata specificazione `readPreference=primary` invia tutte le letture e le scritture all'istanza principale. Per ulteriori opzioni per`readPreference`, vedere. [Leggi le opzioni di preferenza](how-it-works.md#durability-consistency-isolation)

### Scrivi preoccupazioni e scrivi un diario
<a name="connection-string-write-journal"></a>

La preoccupazione relativa alla scrittura determina il livello di riconoscimento richiesto al database per le operazioni di scrittura. I driver MongoDB offrono un'opzione per ottimizzare i file di richiesta di scrittura e di diario. Amazon DocumentDB non prevede che tu imposti write concern e journal e ignora i valori inviati per and `j` (`w`and)`writeConcern`. `journal` DocumentDB scrive sempre i dati con`writeConcern`: `majority` and`journal`: `true` quindi le scritture vengono registrate in modo duraturo sulla maggior parte dei nodi prima di inviare una conferma al client.

### RetryWrites
<a name="connection-string-retry-writes"></a>

**`retryWrites=false`**— DocumentDB non supporta le scritture riutilizzabili e pertanto questo attributo deve essere sempre impostato su. `false`

### Autenticazione IAM
<a name="connection-string-iam-auth"></a>

**`authSource=%24external`e `authMechanism=MONGODB-AWS`** — Questi due parametri vengono utilizzati per l'autenticazione tramite. AWS Identity and Access Management L'autenticazione IAM è attualmente disponibile solo nella versione 5.0 del cluster basata su istanze. Per ulteriori informazioni, consulta [Autenticazione tramite identità IAM](iam-identity-auth.md).

### Pool di connessioni
<a name="connection-string-pool"></a>

Queste opzioni sono disponibili per il pool di connessioni:
+ **`maxPoolSize`**— Imposta il numero massimo di connessioni che possono essere create nel pool. Quando tutte le connessioni sono in uso e arriva una nuova richiesta, attende che una connessione diventi disponibile. L'impostazione predefinita per i driver Java MongoDB è 100.
+ **`minPoolSize`**— Indica il numero minimo di connessioni che devono essere mantenute nel pool in ogni momento. L'impostazione predefinita per i driver Java MongoDB è 0.
+ **`maxIdleTimeMS`**— Determina per quanto tempo una connessione può rimanere inattiva nel pool prima di essere chiusa e rimossa. L'impostazione predefinita per i driver Java MongoDB è 100 millisecondi.
+ **`waitQueueTimeoutMS`**— Configura per quanto tempo un thread deve attendere prima che una connessione diventi disponibile quando il pool raggiunge la dimensione massima. Se una connessione non diventa disponibile entro questo periodo, viene generata un'eccezione. Il valore predefinito per i driver Java MongoDB è 120.000 millisecondi (2 minuti).

### Parametri di timeout della connessione
<a name="connection-string-timeout"></a>

Il timeout è un meccanismo per limitare il periodo di tempo necessario a un'operazione o a un tentativo di connessione prima che venga considerato fallito. I seguenti parametri di timeout sono disponibili per prevenire attese indefinite e gestire l'allocazione delle risorse:
+ **`connectTimeoutMS`**— Configura il tempo di attesa del driver per stabilire una connessione al cluster. L'impostazione predefinita è 10.000 millisecondi (10 secondi).
+ **`socketTimeoutMS`**— Speciifica per quanto tempo il driver aspetterà una risposta dal server per un'operazione non di scrittura. L'impostazione predefinita è 0, (nessun timeout o infinito).
+ **`serverSelectionTimeoutMS`**— Specificare quanto tempo il driver aspetterà per trovare un server disponibile nel cluster. Il valore predefinito per questa impostazione è 30 secondi ed è sufficiente per eleggere una nuova istanza primaria durante il failover.

## Fase 3: Scrivere il codice di connessione
<a name="step3-write-connect-code"></a>

Il seguente esempio di codice mostra come effettuare una connessione TLS ad Amazon DocumentDB:
+ Crea oggetti Java [https://docs.oracle.com/javase/8/docs/api/java/security/KeyStore.html](https://docs.oracle.com/javase/8/docs/api/java/security/KeyStore.html)e [`SSLContext`>](https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/SSLContext.html).
+ Crea anche l'[https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/MongoClientSettings.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/MongoClientSettings.html)oggetto passandolo all'[https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/ConnectionString.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/ConnectionString.html)oggetto. Per stabilire una connessione TLS, è necessario utilizzare l'`MongoClientSettings`oggetto per associare l'`connectionstring`and. `sslcontext`
+ Usando [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoClients.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoClients.html)ottiene un oggetto [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoClient.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoClient.html).

```
public static MongoClient makeDbConnection(String dbName, String DbUserName, String DbPassword,
    String DbClusterEndPoint, String keyStorePass) throws Exception {
    MongoClient connectedClient;
    String connectionOptions = "?replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false";
    String connectionUrl = "mongodb://" + DbUserName + ":" + DbPassword + "@" + DbClusterEndPoint + ":27017/" +
        dbName + connectionOptions;

    try {
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        try (FileInputStream fis = new FileInputStream("src/main/resources/certs/truststore.jks")) {
            trustStore.load(fis, keyStorePass.toCharArray());
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            tmf.init(trustStore);

            SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
            sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());
            ConnectionString connectionString = new ConnectionString(connectionUrl);
            MongoClientSettings settings = MongoClientSettings.builder()
                .applyConnectionString(connectionString)
                .applyToSslSettings(builder - > {
                    builder.enabled(true);
                    builder.context(sslContext);
                })
                .build();
            connectedClient = MongoClients.create(settings);
        }
        return connectedClient;
    } catch (MongoException e5) {
        throw new RuntimeException(e5);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
```

## Fase 4: Gestire le eccezioni di connessione
<a name="step4-handle-connect-exceptions"></a>

Quando si lavora con DocumentDB in applicazioni Java, la gestione delle eccezioni di connessione è fondamentale per mantenere operazioni di database solide e affidabili. Gestite correttamente, queste eccezioni non solo aiutano a diagnosticare rapidamente i problemi, ma garantiscono anche che l'applicazione sia in grado di gestire correttamente le interruzioni temporanee della rete o l'indisponibilità del server, con conseguente miglioramento della stabilità e dell'esperienza utente. Alcune delle eccezioni critiche relative alla creazione di una connessione includono:
+ **`MongoException`**— Un'eccezione generale che potrebbe essere emessa in vari scenari non coperti da eccezioni più specifiche. Assicurati che questa eccezione venga gestita dopo tutte le altre eccezioni specifiche poiché si tratta di un'eccezione catch-all MongoDB generale.
+ **`MongoTimeoutException`**— Emesso in caso di timeout di un'operazione. Ad esempio, interrogando un endpoint del cluster inesistente.
+ **`MongoSocketException`**— Rilasciato per problemi relativi alla rete. Ad esempio, disconnessione improvvisa della rete durante un'operazione. 
+ **`MongoSecurityException`**— Emesso quando l'autenticazione fallisce. Ad esempio, connessione con credenziali errate. 
+ **`MongoConfigurationException`**— Emesso in caso di errore nella configurazione del client. Ad esempio, utilizzando una stringa di connessione non valida.

## Fase 5: Esecuzione del codice
<a name="step5-running-code"></a>

Il seguente esempio di codice crea una connessione Amazon DocumentDB e stampa tutti i database:

```
public static void TestConnection() {
    try (MongoClient mongoClient = makeDbConnection(DATABASE_NAME, DB_USER_NAME, DB_PASSWORD, DB_CLUSTER_ENDPOINT, KEYSTORE_PASSWORD)) {
        List < String > databases = mongoClient.listDatabaseNames().into(new ArrayList < > ());
        System.out.println("Databases: " + databases);
    } catch (MongoException e) {
        System.err.println("MongoDB error: " + e.getMessage());
        throw new RuntimeException(e);
    }
}
```

## Le migliori pratiche di connessione
<a name="java-connect-best-practices"></a>

Di seguito sono riportate le best practice da considerare quando ci si connette ad Amazon DocumentDB con un driver Java MongoDB:
+ Chiudi sempre il tuo [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoClient.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoClient.html)quando non hai più bisogno che il client rilasci risorse.
+ Gestisci le eccezioni in modo appropriato e implementa una corretta registrazione degli errori.
+ Utilizza variabili di ambiente o Gestione dei segreti AWS per archiviare informazioni sensibili come nomi utente e password.

# Esecuzione di operazioni CRUD in Amazon DocumentDB con Java
<a name="java-crud-operations"></a>

Questa sezione descrive l'esecuzione dell'operazione CRUD (creazione, lettura, aggiornamento, eliminazione) in Amazon DocumentDB utilizzando i driver Java MongoDB.

**Topics**
+ [

## Creazione e inserimento di documenti in una raccolta DocumentDB
](#creating-inserting)
+ [

## Lettura e recupero di dati da una raccolta DocumentDB
](#reading-retrieving)
+ [

## Aggiornamento di documenti esistenti in una raccolta DocumentDB
](#updating-documents)
+ [

## Rimuovere documenti da una raccolta DocumentDB
](#deleting-documents)
+ [

## Gestione degli errori con la logica di ripetizione
](#error-handling)

## Creazione e inserimento di documenti in una raccolta DocumentDB
<a name="creating-inserting"></a>

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 [BsonDocument](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/bson/org/bson/BsonDocument.html)per l'inserimento e restituisce un [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/result/InsertOneResult.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/result/InsertOneResult.html)oggetto 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'utilizzo`insertOne()`, 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 segue`MongoWriteException`:

```
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 [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/result/InsertManyResult.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/result/InsertManyResult.html)`InsertManyResult`oggetto 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());
```

**[https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/bulk/package-summary.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/bulk/package-summary.html)**

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, come l'inserimento di alcuni documenti e l'aggiornamento di 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 [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/WriteModel.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/WriteModel.html)classe funge da classe base per tutte le operazioni di scrittura e con implementazioni specifiche come [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/InsertOneModel.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/InsertOneModel.html),, [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/UpdateOneModel.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/UpdateOneModel.html), e la [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/DeleteManyModel.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/DeleteManyModel.html)gestione di diversi tipi di operazioni.

La [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/BulkWriteOptions.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/BulkWriteOptions.html)classe è necessaria per configurare il comportamento delle operazioni di massa, come impostare l' ordered/unordered esecuzione o ignorare la convalida dei documenti. La [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/bulk/BulkWriteResult.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/bulk/BulkWriteResult.html)classe fornisce informazioni dettagliate sui risultati dell'esecuzione, incluso il conteggio dei documenti inseriti, aggiornati ed eliminati.

Per la gestione degli errori, la [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/MongoBulkWriteException.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/MongoBulkWriteException.html)classe è fondamentale in quanto contiene informazioni su eventuali errori durante l'operazione in blocco, mentre la [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/bulk/BulkWriteError.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/bulk/BulkWriteError.html)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'ambito dell'esecuzione di una singola chiamata al metodo. `bulkWrite()` Il codice mostra anche come utilizzare [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/BulkWriteOptions.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/BulkWriteOptions.html)e [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/bulk/BulkWriteResult.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/bulk/BulkWriteResult.html)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());
}
```

**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 ripetizione](#error-handling)Di 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
<a name="reading-retrieving"></a>

L'interrogazione di documenti in Amazon DocumentDB ruota attorno a diversi componenti chiave che consentono di recuperare e manipolare i dati con precisione. Il [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoCollection.html#find()](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoCollection.html#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, [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/Filters.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/Filters.html)e [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/FindIterable.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/FindIterable.html)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 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 specifica`limit(n)`, DocumentDB smetterà di restituire documenti dopo aver restituito 'n' documenti, anche se ci sono più corrispondenze nel database. 

`FindIterable`supporta 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. 

`FindIterable`forniscono inoltre il supporto per [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoCursor.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoCursor.html)cui è 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'`AutoCloseable`interfaccia, 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 di`find()`, `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 a`find()`:

```
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 con`find()`:

```
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()` e`batchSize()`.

```
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 su`FindIterable`. 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
<a name="updating-documents"></a>

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`updateOne()`: per l'aggiornamento di singoli documenti`updateMany()`, per l'aggiornamento di più documenti `replaceOne()` e per la sostituzione completa dei documenti. Oltre a questi tre metodi, [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/Updates.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/Updates.html), e [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/result/UpdateResult.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/result/UpdateResult.html)ci 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 tramite`upsert(true)`, consente la creazione di nuovi documenti quando non vengono trovati documenti corrispondenti durante un'operazione di aggiornamento. Tramite`arrayFilters()`, l'operazione di aggiornamento può aggiornare con precisione gli elementi dell'array che soddisfano criteri specifici.

`UpdateResult`nel 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
<a name="update-single-doc"></a>

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'`UpdateResult`oggetto.

```
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
<a name="update-multiple-docs"></a>

Esistono due modi per aggiornare più documenti in una raccolta contemporaneamente. È possibile utilizzare il `updateMany()` metodo o utilizzare il [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/UpdateManyModel.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/UpdateManyModel.html)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 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
<a name="deleting-documents"></a>

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 [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/result/DeleteResult.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/result/DeleteResult.html)oggetto 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
<a name="error-handling"></a>

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 [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/MongoException.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/MongoException.html)e 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);
    }
}
```

# Gestione degli indici in Amazon DocumentDB con Java
<a name="index-management-java"></a>

Gli indici consentono il recupero efficiente dei dati da una raccolta Amazon DocumentDB. Senza indici, DocumentDB deve scansionare ogni documento della raccolta per restituire risultati che soddisfino una determinata query. Questo argomento fornisce informazioni su come creare, eliminare ed elencare gli indici utilizzando i driver Java MongoDB. Descrive inoltre come determinare se un particolare indice viene utilizzato nella query e come fornire suggerimenti ad Amazon DocumentDB per utilizzare un indice specifico.

**Topics**
+ [Creazione di indici](#creating-indexes)
+ [Eliminazione degli indici](#dropping-indes)
+ [Determinare la selezione dell'indice e fornire un suggerimento sull'indice](#w2aac43b9b7c17c13)

Amazon DocumentDB supporta molti tipi di indici. [Per una panoramica completa di tutti gli indici supportati, consulta questo post di blog.](https://aws.amazon.com/blogs/database/how-to-index-on-amazon-documentdb-with-mongodb-compatibility/) 

## Creazione di indici con Java
<a name="creating-indexes"></a>

Esistono due meccanismi per creare indici in Amazon DocumentDB utilizzando i driver Java MongoDB`runCommand()`: tramite e con il metodo per un singolo indice `createIndex()` o il metodo per più indici. `createIndexes()` Uno dei motivi per utilizzare i `createIndexes()` metodi `createIndex()` and è che è possibile migliorare la gestione degli errori rilevando errori specifici relativi alla creazione dell'indice. Un altro motivo per utilizzare questo metodo `runCommand()` è che il driver Java MongDB fornisce un ricco set di classi di supporto per la creazione e la manipolazione degli indici. Nota che queste classi di supporto possono essere utilizzate solo quando si utilizzano i `createIndex()` metodi or. `createIndexes()` Esistono tre classi di supporto:
+ **[https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/Indexes.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/Indexes.html)**— Questa classe funge da classe di utilità che offre metodi di fabbrica statici per la creazione di vari tipi di indici. Semplifica il processo di creazione di definizioni di indici complesse ed è comunemente utilizzata insieme ad altre classi relative agli indici.
+ **[https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/IndexModel.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/IndexModel.html)**— Questa è una classe fondamentale che incapsula sia la definizione delle chiavi dell'indice che le relative opzioni. Rappresenta una specifica completa dell'indice, che combina cosa indicizzare (le chiavi) con come indicizzare (le opzioni). Questa classe è particolarmente utile quando si creano più indici contemporaneamente, in quanto consente di definire una raccolta di specifiche dell'indice che possono essere passate al `createIndexes()` metodo.
+ **[https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/IndexOptions.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/IndexOptions.html)**— Si tratta di una classe di configurazione completa che fornisce un ricco set di metodi per personalizzare il comportamento dell'indice. Include impostazioni per indici univoci, indici sparsi, data di scadenza (TTL) ed espressioni di filtro parziali. Tramite il concatenamento dei metodi, puoi configurare più opzioni come la creazione di indici in background e i vincoli unici.

**Crea un indice singolo**

Questo esempio mostra come creare un singolo indice utilizzando il metodo`createIndex(`) in background. Per comprendere la creazione di indici in background e in primo piano, consulta. [Tipi di compilazione dell'indice](managing-indexes.md#index-build-types) Il seguente esempio di codice utilizza la creazione [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/IndexOptions.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/IndexOptions.html)di un indice univoco con il nome «Unique\$1restaurantid\$1idx» in background. Questo `IndexOptions` oggetto viene quindi passato al metodo. `createIndex()`

```
collection.createIndex(
    Indexes.ascending("restaurantId"),
    new IndexOptions()
        .unique(true)
        .name("unique_restaurantId_idx")
        .background(true));
```

**Crea più indici**

Questo esempio crea più indici utilizzando il metodo. `createIndexes()` Innanzitutto crea l'opzione per ogni indice utilizzando l'[https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/IndexModel.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/IndexModel.html)oggetto, quindi passa un elenco di `IndexModel` oggetti al metodo. `createIndexes()` L'esempio di codice seguente mostra come creare un indice composito utilizzando la classe di [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/Indexes.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/Indexes.html)utilità. Questa classe viene anche utilizzata per specificare se si desidera creare un indice utilizzando un ordinamento crescente o decrescente. Dopo aver creato più indici, verifica la creazione dell'indice chiamando il metodo. `listIndexes()`

```
// Single Field Index on cuisine
IndexModel singleIndex = new IndexModel(
    Indexes.ascending("cuisine"),
    new IndexOptions().name("cuisine_idx"));

// Compound Index
IndexModel compoundIndex = new IndexModel(
    Indexes.compoundIndex(
        Indexes.ascending("address.state"),
        Indexes.ascending("priceRange")),
    new IndexOptions().name("location_price_idx"));

// Build a list of IndexModel for the indexes
List < IndexModel > indexes = Arrays.asList(
    singleIndex,
    compoundIndex
);

collection.createIndexes(indexes);

// Verify created indexes
collection.listIndexes().forEach(index - > System.out.println("Created index: " + index.toJson()));
```

**Crea indici sparsi e parziali**

Questo esempio mostra come crea un indice sparso e uno parziale creando un indice [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/IndexModel.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/IndexModel.html)per ogni tipo di indice.

```
// Sparse Index Model, this will identify only those documents that have a
// michelin star rating
IndexModel sparseIndex = new IndexModel(
    Indexes.ascending("michelin.star"),
    new IndexOptions()
    .name("michelin_sparse_idx")
    .sparse(true));

// Partial Index Model where the restaurant is active and has a rating of 4 and above
IndexModel partialIndex = new IndexModel(
    Indexes.ascending("rating.average"),
    new IndexOptions()
    .name("high_rated_active_idx")
    .partialFilterExpression(
        Filters.and(
            Filters.eq("isActive", true),
            Filters.gte("rating.average", 4.0))));
```

**Crea un indice di testo**

Questo esempio mostra come creare un indice di testo. È consentito un solo indice di testo in una raccolta, ma quell'indice di testo può essere un indice composto che copre più campi. Quando si utilizzano più campi nell'indice di testo, è inoltre possibile assegnare dei pesi a ciascuno dei campi dell'indice. Gli indici di testo nei campi array non sono supportati da Amazon DocumentDB e anche se è possibile utilizzare fino a 30 campi nell'indice di testo composto, è possibile assegnare un peso solo a tre campi.

```
IndexModel textIndex = new IndexModel(
    new Document()
    .append("name", "text")
    .append("description", "text")
    .append("cuisine", "text"),
    new IndexOptions()
    .name("restaurant_text_idx")
    .weights(new Document()
        .append("name", 10) // Restaurant name gets highest weight
        .append("description", 5) // Description get medium weight
        .append("cuisine", 2) // Cuisine type gets low weight
    ));

collection.createIndex(textIndex.getKeys(), textIndex.getOptions());
```

**Crea un indice utilizzando `runCommand()`**

Amazon DocumentDB supporta la creazione di indici paralleli per ridurre il tempo necessario per creare gli indici. L'indicizzazione parallela utilizza più lavoratori simultanei. I worker predefiniti utilizzati per la creazione dell'indice sono due. Questo [post del blog](https://aws.amazon.com/blogs/database/unlock-the-power-of-parallel-indexing-in-amazon-documentdb/) fornisce una discussione approfondita sull'indicizzazione parallela. Attualmente, i driver Java per MongDB non supportano la specificazione dell'opzione worker quando si utilizza `createIndex()` `createIndexes()` e quindi l'unico modo per specificare i worker è tramite. `runCommand` Il seguente esempio di codice mostra come creare un indice che aumenti il numero di lavoratori `runCommand` a quattro:

```
Document command = new Document("createIndexes", "Restaurants")
    .append("indexes", Arrays.asList(
        new Document("key", new Document("name", 1))
        .append("name", "restaurant_name_idx")
        .append("workers", 4) // Specify number of workers
    ));

Document commendResult = connectedDB.runCommand(command);
```

## Eliminazione degli indici
<a name="dropping-indes"></a>

Il driver Java MongoDB offre diversi metodi per eliminare gli indici, in base a diversi scenari e alle tue preferenze. Puoi eliminare gli indici per nome, per specifica chiave o eliminare tutti gli indici contemporaneamente. I metodi `dropIndex()` e `dropIndexes()` possono essere richiamati su un oggetto della raccolta per eliminare un indice. Quando si elimina un indice per nome, è necessario assicurarsi che utilizzi il nome dell'indice corretto, che potrebbe non essere sempre intuitivo, specialmente per gli indici composti o generati automaticamente. Il tentativo di eliminare un indice inesistente produrrà un. [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/MongoCommandException.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/MongoCommandException.html) L'`default _id`indice non può essere eliminato in quanto garantisce l'unicità del documento all'interno della raccolta.

Il seguente esempio di codice mostra come eliminare un indice fornendo il nome del campo in cui viene creato l'indice o eliminando tutti gli indici: 

```
String indexName = "unique_restaurantId_idx";
Document keys = new Document("cuisine", 1);
// Drop index by name
collection.dropIndex(indexName);
            
// Drop index by keys
collection.dropIndex(keys);
            
// Drop all indexes
collection.dropIndexes();
```

Quando eliminate gli indici utilizzando più chiavi, assicuratevi che vi sia un indice composto contenente tutte le chiavi specificate e che l'ordine delle chiavi sia corretto. Il codice di esempio per la creazione dell'indice sopra riportato mostra una chiave composta su «cucina» e funzionalità. Se provate a eliminare quella chiave composta ma l'ordine non corrisponde a quello usato per la creazione, si verifica un MongoCommnadException errore come segue:

```
Document keys = new Document("features", 1)
    .append("cuisine", 1);
try {
    // Drop index by keys
    collection.dropIndex(keys);
    System.out.println("Successfully dropped index with keys: " + keys.toJson());

} catch (MongoCommandException commErr) {
    System.out.println("Error dropping index: " + commErr.getErrorMessage());
    throw new RuntimeException("MongoCommandException was thrown while dropping index", commErr);
}
```

Viene visualizzato l'errore seguente:

```
Error dropping index: Cannot drop index: index not found.
Tests run: 3, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.819 sec <<< FAILURE!
com.amazon.docdb.guide.DocDBGuideTest.testindexGuide()  Time elapsed: 0.817 sec  <<< FAILURE!
org.opentest4j.AssertionFailedError: Unexpected exception thrown: java.lang.RuntimeException: MongoCommandException was thrown while dropping index
```

## Determinare la selezione dell'indice e fornire un suggerimento sull'indice
<a name="w2aac43b9b7c17c13"></a>

Utilizzare la funzionalità di spiegazione di Amazon DocumentDB è fondamentale per comprendere le prestazioni delle query e l'utilizzo degli indici. Quando si esegue una query, è possibile aggiungere il `explain()` metodo per ottenere informazioni dettagliate sul piano di query, inclusi gli eventuali indici utilizzati. L'`explain()`output fornisce informazioni sulle fasi di esecuzione delle query, sul numero di documenti esaminati e sul tempo impiegato per ciascuna fase. Queste informazioni sono preziose per determinare se un determinato indice viene utilizzato in modo efficace o se la query potrebbe trarre vantaggio da una diversa struttura dell'indice.

Il `explain()` metodo può essere concatenato al `find()` metodo. Il `explain()` metodo può utilizzare un [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/ExplainVerbosity.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/ExplainVerbosity.html)enum opzionale che determina il livello di verbosità restituito da. `explain()` Al momento, solo gli `QUERY_PLANNER` enumeratori `EXECUTION_STATS` e sono supportati da DocumentDB. Il seguente esempio di codice mostra come ottenere il pianificatore di query per una query specifica:

```
// Query we want to analyze
Document query = new Document()
    .append("cuisine", "Thai")
    .append("rating.average", new Document("$gte", 4.0));


Document allPlansExplain = collection.find(query).explain(ExplainVerbosity.QUERY_PLANNER);
System.out.println("All Plans Explain:\n" + allPlansExplain.toJson());
```

Il seguente documento JSON viene restituito per il livello di verbosità del pianificatore di query:

```
{
  "queryPlanner": {
    "plannerVersion": 1,
    "namespace": "ProgGuideData.Restaurants",
    "winningPlan": {
      "stage": "IXSCAN",
      "indexName": "cuisine_idx",
      "direction": "forward"
    }
  },
  "serverInfo": {
    "host": "guidecluster3",
    "port": 27017,
    "version": "5.0.0"
  },
  "ok": 1,
  "operationTime": {
    "$timestamp": {
      "t": 1739221668,
      "i": 1
    }
  }
}
```

Sono disponibili diverse opzioni per influenzare o forzare Amazon DocumentDB a utilizzare un indice specifico. `hintString()`I metodi `hint()` and consentono di sovrascrivere il comportamento di selezione dell'indice predefinito di Query Optimizer specificando esplicitamente quale indice deve essere utilizzato per una query. Sebbene l'ottimizzatore di query di DocumentDB in genere rappresenti buone scelte per la selezione degli indici, ci sono scenari in cui forzare l'esecuzione di un indice specifico `hint()` o `hintString()` può essere utile, ad esempio quando si tratta di dati distorti o si testano le prestazioni dell'indice.

Il seguente esempio di codice impone l'uso dell'indice composto «cuisine\$1features\$1idx» per la stessa query eseguita nel codice precedente:

```
// Query we want to analyze
Document query = new Document()
    .append("cuisine", "Thai")
    .append("rating.average", new Document("$gte", 4.0));

List < Document > queryDocs = new ArrayList < > ();
collection.find(query).hintString("cuisine_features_idx").forEach(doc - > queryDocs.add(doc));
```

# Programmazione basata sugli eventi con Amazon DocumentDB e Java
<a name="event-driven-programming"></a>

La programmazione basata sugli eventi nel contesto di Amazon DocumentDB rappresenta un potente modello architettonico in cui le modifiche al database fungono da generatori di eventi principali che attivano la logica e i processi aziendali successivi. Quando i record vengono inseriti, aggiornati o eliminati in una raccolta DocumentDB, queste modifiche agiscono come eventi che avviano automaticamente vari processi, notifiche o attività di sincronizzazione dei dati a valle. Questo modello è particolarmente utile nei moderni sistemi distribuiti in cui più applicazioni o servizi devono reagire alle modifiche dei dati in tempo reale. Il meccanismo principale di implementazione della programmazione basata sugli eventi in DocumentDB è costituito dai flussi di modifiche.

**Nota**  
Questa guida presuppone che tu abbia abilitato i flussi di modifica su una raccolta con cui stai lavorando. Scopri come abilitare i flussi di modifica nella raccolta. [Utilizzo dei flussi di modifica con Amazon DocumentDB](change_streams.md) 

**Utilizzo dei flussi di modifica dall'applicazione Java**

Il `watch()` metodo del driver Java di MongoDB è il meccanismo principale per monitorare le modifiche dei dati in tempo reale in Amazon DocumentDB. Il `watch()` metodo può essere richiamato da [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoClient.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoClient.html), e objects. [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoCollection.html#watch()](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoCollection.html#watch())

Il `watch()` metodo restituisce un'istanza [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/ChangeStreamIterable.html#startAtOperationTime(org.bson.BsonTimestamp)](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/ChangeStreamIterable.html#startAtOperationTime(org.bson.BsonTimestamp))che supporta varie opzioni di configurazione, tra cui la ricerca completa dei documenti per gli aggiornamenti, la fornitura di token di curriculum e timestamp per l'affidabilità e le fasi di aggregazione della pipeline per filtrare le modifiche. 

[https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/ChangeStreamIterable.html#startAtOperationTime(org.bson.BsonTimestamp)](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/ChangeStreamIterable.html#startAtOperationTime(org.bson.BsonTimestamp))implementa l'interfaccia Java di base e può essere utilizzato con. `Iterable` `forEach()` Per acquisire gli eventi utilizzando`forEach()`, passa una funzione di callback `forEach()` che elabora l'evento modificato. Il seguente frammento di codice mostra come aprire un flusso di modifiche su una raccolta per avviare il monitoraggio degli eventi di modifica:

```
ChangeStreamIterable < Document > iterator = collection.watch();
iterator.forEach(event - > {
    System.out.println("Received a change: " + event);
});
```

Un altro modo per attraversare tutti gli eventi di modifica consiste nell'aprire un cursore che mantiene una connessione al cluster e riceve continuamente nuovi eventi di modifica man mano che si verificano. Per ottenere un cursore Change Streams, utilizzate il metodo dell'oggetto. `cursor()` [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/ChangeStreamIterable.html#startAtOperationTime(org.bson.BsonTimestamp)](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/ChangeStreamIterable.html#startAtOperationTime(org.bson.BsonTimestamp)) Il seguente esempio di codice mostra come monitorare gli eventi di modifica utilizzando il cursore:

```
try (MongoChangeStreamCursor < ChangeStreamDocument < Document >> cursor = collection.watch().cursor()) {
    System.out.println(cursor.tryNext());
}
```

Come procedura ottimale, create il comando [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoChangeStreamCursor.html#getResumeToken()](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/MongoChangeStreamCursor.html#getResumeToken())in un' try-with-resourceistruzione o chiudete manualmente il cursore. La chiamata al `cursor()` metodo on [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/ChangeStreamIterable.html#startAtOperationTime(org.bson.BsonTimestamp)](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/ChangeStreamIterable.html#startAtOperationTime(org.bson.BsonTimestamp))`MongoChangeStreamCursor`restituisce un messaggio creato su un [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/changestream/ChangeStreamDocument.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/changestream/ChangeStreamDocument.html)oggetto. 

La [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/changestream/ChangeStreamDocument.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/changestream/ChangeStreamDocument.html)classe è un componente cruciale che rappresenta i singoli eventi di modifica nello stream. Contiene informazioni dettagliate su ogni modifica, incluso il tipo di operazione (inserimento, aggiornamento, eliminazione, sostituzione), la chiave del documento, le informazioni sullo spazio dei nomi e il contenuto completo del documento, se disponibile. La classe fornisce metodi per accedere a vari aspetti dell'evento di modifica, `getOperationType()` ad esempio per determinare il tipo di modifica, accedere `getFullDocument()` allo stato completo del documento e `getDocumentKey()` identificare il documento modificato.

L'[https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/changestream/ChangeStreamDocument.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/changestream/ChangeStreamDocument.html)oggetto fornisce due informazioni importanti, un token di ripristino e l'ora dell'evento di modifica.

I token di ripresa e le operazioni basate sul tempo nei flussi di modifica di DocumentDB forniscono meccanismi cruciali per mantenere la continuità e gestire l'accesso ai dati storici. Un token di ripristino è un identificatore univoco generato per ogni evento di modifica, che funge da segnalibro che consente alle applicazioni di riavviare l'elaborazione del flusso di modifiche da un punto specifico dopo disconnessioni o errori. Quando viene creato un cursore del flusso di modifica, può utilizzare un token di ripristino precedentemente memorizzato tramite `resumeAfter()` l'opzione, che consente allo stream di continuare da dove era stato interrotto anziché ricominciare dall'inizio o perdere gli eventi.

Le operazioni basate sul tempo nei flussi di modifica offrono approcci diversi per gestire il punto di partenza del monitoraggio degli eventi di modifica. L'`startAtOperationTime()`opzione consente di iniziare a guardare le modifiche avvenute in corrispondenza o dopo un determinato timestamp. Queste funzionalità basate sul tempo sono particolarmente utili in scenari che richiedono l'elaborazione, il point-in-time ripristino o la sincronizzazione dei dati storici tra i sistemi.

Il seguente esempio di codice recupera l'evento associato al documento di inserimento, ne acquisisce il token di ripristino e quindi lo fornisce per avviare il monitoraggio degli eventi successivi all'evento di inserimento. L'evento viene associato all'evento di aggiornamento, quindi ottiene l'ora del cluster in cui è avvenuto l'aggiornamento e utilizza tale timestamp come punto di partenza per l'ulteriore elaborazione.

```
BsonDocument resumeToken;
BsonTimestamp resumeTime;

try (MongoChangeStreamCursor < ChangeStreamDocument < Document >> cursor = collection.watch().cursor()) {
    System.out.println("****************** Insert Document *******************");
    ChangeStreamDocument < Document > insertChange = cursor.tryNext();
    resumeToken = insertChange.getResumeToken();
    printJson(cursor.tryNext());
}
try (MongoChangeStreamCursor < ChangeStreamDocument < Document >> cursor = collection.watch()
    .resumeAfter(resumeToken)
    .cursor()) {
    System.out.println("****************** Update Document *******************");
    ChangeStreamDocument < Document > insertChange = cursor.tryNext();
    resumeTime = insertChange.getClusterTime();
    printJson(cursor.tryNext());
}
try (MongoChangeStreamCursor < ChangeStreamDocument < Document >> cursor = collection.watch()
    .startAtOperationTime(resumeTime)
    .cursor()) {
    System.out.println("****************** Delete Document *******************");
    printJson(cursor.tryNext());
  }
```

Per impostazione predefinita, l'evento di modifica dell'aggiornamento non include il documento completo e include solo le modifiche apportate. Se è necessario accedere al documento completo che è stato aggiornato, è possibile chiamare il `fullDocument()` metodo sull'[https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/ChangeStreamIterable.html#startAtOperationTime(org.bson.BsonTimestamp)](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-sync/com/mongodb/client/ChangeStreamIterable.html#startAtOperationTime(org.bson.BsonTimestamp))oggetto. Tenete presente che quando richiedete la restituzione di un documento completo per un evento di aggiornamento, viene restituito il documento esistente al momento della chiamata per modificare i flussi.

Questo metodo accetta un [https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/changestream/FullDocument.html](https://mongodb.github.io/mongo-java-driver/5.3/apidocs/mongodb-driver-core/com/mongodb/client/model/changestream/FullDocument.html)enum come parametro. Attualmente, Amazon DocumentDB supporta solo DEFAULT e `UPDATE_LOOKUP` valori. Il seguente frammento di codice mostra come richiedere il documento completo per gli eventi di aggiornamento quando si inizia a controllare le modifiche:

```
try (MongoChangeStreamCursor < ChangeStreamDocument < Document >> cursor = collection.watch().fullDocument(FullDocument.UPDATE_LOOKUP).cursor())
```