

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

# Lavora con risultati impaginati: scansioni e interrogazioni
<a name="ddb-en-client-use-multirecord"></a>

*I `scan` `batch` metodi `query` e dell'API DynamoDB Enhanced Client restituiscono risposte con una o più pagine.* Una pagina contiene uno o più elementi. Il codice può elaborare la risposta per pagina o elaborare singoli elementi.

Una risposta impaginata restituita dal client sincrono restituisce un [PageIterable](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/PageIterable.html)oggetto, mentre una risposta restituita dal `DynamoDbEnhancedClient` client asincrono restituisce un oggetto. `DynamoDbEnhancedAsyncClient` [PagePublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/PagePublisher.html)

Questa sezione esamina l'elaborazione dei risultati impaginati e fornisce esempi che utilizzano la scansione e l'interrogazione. APIs

## Esegui la scansione di una tabella
<a name="ddb-en-client-use-multirecord-scan"></a>

Il [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbAsyncTable.html#scan(java.util.function.Consumer)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbAsyncTable.html#scan(java.util.function.Consumer))metodo dell'SDK corrisponde all'operazione [DynamoDB con lo stesso nome](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Scan.html). L'API DynamoDB Enhanced Client offre le stesse opzioni, ma utilizza un modello a oggetti familiare e gestisce l'impaginazione al posto tuo.

Innanzitutto, esploriamo l'`PageIterable`interfaccia esaminando il `scan` metodo della classe di mappatura sincrona,. [DynamoDbTable](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html)

### Usa l'API sincrona
<a name="ddb-en-client-use-multirecord-scan-sync"></a>

L'esempio seguente mostra il `scan` metodo che utilizza un'[espressione](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/Expression.html) per filtrare gli elementi restituiti. [ProductCatalog](ddb-en-client-use.md#ddb-en-client-use-compare-cs3)È l'oggetto modello che è stato mostrato in precedenza.

L'espressione di filtro mostrata dopo la riga di commento 2 limita gli `ProductCatalog` articoli che vengono restituiti a quelli con un valore di prezzo compreso tra 8,00 e 80,00 inclusi.

Questo esempio esclude anche `isbn` i valori utilizzando il `attributesToProject` metodo mostrato dopo la riga di commento 1.

Dopo la riga di commento 3, l'`PageIterable`oggetto,`pagedResults`, viene restituito dal `scan` metodo. Il `stream` metodo di `PageIterable` restituisce un [https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html)oggetto, che è possibile utilizzare per elaborare le pagine. In questo esempio, il numero di pagine viene contato e registrato.

A partire dalla riga di commento 4, l'esempio mostra due varianti di accesso agli `ProductCatalog` elementi. La versione successiva alla riga di commento 4a scorre attraverso ogni pagina e ordina e registra gli elementi su ogni pagina. La versione successiva alla riga di commento 4b salta l'iterazione della pagina e accede direttamente agli elementi.

L'`PageIterable`interfaccia offre diversi modi per elaborare i risultati grazie alle sue due interfacce principali: e. [https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html](https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html) `Iterable`porta i `spliterator` metodi`forEach`, `iterator` e `SdkIterable` porta il `stream` metodo.

```
    public static void scanSync(DynamoDbTable<ProductCatalog> productCatalog) {

        Map<String, AttributeValue> expressionValues = Map.of(
                ":min_value", numberValue(8.00),
                ":max_value", numberValue(80.00));

        ScanEnhancedRequest request = ScanEnhancedRequest.builder()
                .consistentRead(true)
                // 1. the 'attributesToProject()' method allows you to specify which values you want returned.
                .attributesToProject("id", "title", "authors", "price")
                // 2. Filter expression limits the items returned that match the provided criteria.
                .filterExpression(Expression.builder()
                        .expression("price >= :min_value AND price <= :max_value")
                        .expressionValues(expressionValues)
                        .build())
                .build();

        // 3. A PageIterable object is returned by the scan method.
        PageIterable<ProductCatalog> pagedResults = productCatalog.scan(request);
        logger.info("page count: {}", pagedResults.stream().count());

        // 4. Log the returned ProductCatalog items using two variations.
        // 4a. This version sorts and logs the items of each page.
        pagedResults.stream().forEach(p -> p.items().stream()
                .sorted(Comparator.comparing(ProductCatalog::price))
                .forEach(
                        item -> logger.info(item.toString())
                ));
        // 4b. This version sorts and logs all items for all pages.
        pagedResults.items().stream()
                .sorted(Comparator.comparing(ProductCatalog::price))
                .forEach(
                        item -> logger.info(item.toString())
                );
    }
```

### Usa l'API asincrona
<a name="ddb-en-client-use-multirecord-scan-async"></a>

Il `scan` metodo asincrono restituisce i risultati come oggetto. `PagePublisher` L'`PagePublisher`interfaccia dispone di due `subscribe` metodi che è possibile utilizzare per elaborare le pagine di risposta. Un `subscribe` metodo proviene dall'interfaccia `org.reactivestreams.Publisher` principale. Per elaborare le pagine utilizzando questa prima opzione, passate un'`[Subscriber](https://www.reactive-streams.org/reactive-streams-1.0.0-javadoc/org/reactivestreams/Subscriber.html)`istanza al `subscribe` metodo. Il primo esempio che segue mostra l'uso del `subscribe` metodo.

Il secondo `subscribe` metodo proviene dall'[SdkPublisher](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/SdkPublisher.html)interfaccia. Questa versione di `subscribe` accetta a [https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html](https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html)anziché a`Subscriber`. Questa variazione di `subscribe` metodo è illustrata nel secondo esempio che segue.

L'esempio seguente mostra la versione asincrona del `scan` metodo che utilizza la stessa espressione di filtro mostrata nell'esempio precedente. 

Dopo la riga di commento 3, `DynamoDbAsyncTable.scan` restituisce un oggetto. `PagePublisher` Nella riga successiva, il codice crea un'istanza dell'`org.reactivestreams.Subscriber`interfaccia`ProductCatalogSubscriber`, che sottoscrive la riga 4 `PagePublisher` dopo il commento.

L'`Subscriber`oggetto raccoglie gli `ProductCatalog` elementi da ogni pagina del `onNext` metodo dopo la riga di commento 8 nell'esempio di `ProductCatalogSubscriber` classe. Gli elementi sono memorizzati nella `List` variabile privata e vi si accede nel codice di chiamata con il `ProductCatalogSubscriber.getSubscribedItems()` metodo. Viene chiamato dopo la riga di commento 5.

Dopo aver recuperato l'elenco, il codice ordina tutti gli `ProductCatalog` articoli in base al prezzo e registra ogni articolo.

La `ProductCatalogSubscriber` classe [CountDownLatch](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html)in the blocca il thread chiamante fino a quando tutti gli elementi non sono stati aggiunti all'elenco prima di continuare dopo la riga di commento 5. 

```
    public static void scanAsync(DynamoDbAsyncTable productCatalog) {
        ScanEnhancedRequest request = ScanEnhancedRequest.builder()
                .consistentRead(true)
                .attributesToProject("id", "title", "authors", "price")
                .filterExpression(Expression.builder()
                        // 1. :min_value and :max_value are placeholders for the values provided by the map
                        .expression("price >= :min_value AND price <= :max_value")
                        // 2. Two values are needed for the expression and each is supplied as a map entry.
                        .expressionValues(
                                Map.of( ":min_value", numberValue(8.00),
                                        ":max_value", numberValue(400_000.00)))
                        .build())
                .build();

        // 3. A PagePublisher object is returned by the scan method.
        PagePublisher<ProductCatalog> pagePublisher = productCatalog.scan(request);
        ProductCatalogSubscriber subscriber = new ProductCatalogSubscriber();
        // 4. Subscribe the ProductCatalogSubscriber to the PagePublisher.
        pagePublisher.subscribe(subscriber);
        // 5. Retrieve all collected ProductCatalog items accumulated by the subscriber.
        subscriber.getSubscribedItems().stream()
                .sorted(Comparator.comparing(ProductCatalog::price))
                .forEach(item ->
                        logger.info(item.toString()));
        // 6. Use a Consumer to work through each page.
        pagePublisher.subscribe(page -> page
                        .items().stream()
                        .sorted(Comparator.comparing(ProductCatalog::price))
                        .forEach(item ->
                                logger.info(item.toString())))
                .join(); // If needed, blocks the subscribe() method thread until it is finished processing.
        // 7. Use a Consumer to work through each ProductCatalog item.
        pagePublisher.items()
                .subscribe(product -> logger.info(product.toString()))
                .exceptionally(failure -> {
                    logger.error("ERROR  - ", failure);
                    return null;
                })
                .join(); // If needed, blocks the subscribe() method thread until it is finished processing.
    }
```

```
    private static class ProductCatalogSubscriber implements Subscriber<Page<ProductCatalog>> {
        private CountDownLatch latch = new CountDownLatch(1);
        private Subscription subscription;
        private List<ProductCatalog> itemsFromAllPages = new ArrayList<>();

        @Override
        public void onSubscribe(Subscription sub) {
            subscription = sub;
            subscription.request(1L);
            try {
                latch.await(); // Called by main thread blocking it until latch is released.
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

        @Override
        public void onNext(Page<ProductCatalog> productCatalogPage) {
            // 8. Collect all the ProductCatalog instances in the page, then ask the publisher for one more page.
            itemsFromAllPages.addAll(productCatalogPage.items());
            subscription.request(1L);
        }

        @Override
        public void onError(Throwable throwable) {
        }

        @Override
        public void onComplete() {
            latch.countDown(); // Call by subscription thread; latch releases.
        }

        List<ProductCatalog> getSubscribedItems() {
            return this.itemsFromAllPages;
        }
    }
```

Il seguente esempio di frammento utilizza la versione del `PagePublisher.subscribe` metodo che accetta una riga `Consumer` successiva al commento 6. Il parametro Java lambda utilizza le pagine, che elaborano ulteriormente ogni elemento. In questo esempio, ogni pagina viene elaborata e gli elementi di ogni pagina vengono ordinati e quindi registrati.

```
        // 6. Use a Consumer to work through each page.
        pagePublisher.subscribe(page -> page
                        .items().stream()
                        .sorted(Comparator.comparing(ProductCatalog::price))
                        .forEach(item ->
                                logger.info(item.toString())))
                .join(); // If needed, blocks the subscribe() method thread until it is finished processing.
```

Il `items` metodo di `PagePublisher` decodifica le istanze del modello in modo che il codice possa elaborare direttamente gli elementi. Questo approccio è illustrato nel frammento seguente.

```
        // 7. Use a Consumer to work through each ProductCatalog item.
        pagePublisher.items()
                .subscribe(product -> logger.info(product.toString()))
                .exceptionally(failure -> {
                    logger.error("ERROR  - ", failure);
                    return null;
                })
                .join(); // If needed, blocks the subscribe() method thread until it is finished processing.
```

## Eseguire una query su una tabella
<a name="ddb-en-client-use-multirecord-query"></a>

È possibile utilizzare il DynamoDB Enhanced Client per interrogare la tabella e recuperare più elementi che soddisfano criteri specifici. Il [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html#query(software.amazon.awssdk.enhanced.dynamodb.model.QueryEnhancedRequest)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html#query(software.amazon.awssdk.enhanced.dynamodb.model.QueryEnhancedRequest))metodo trova gli elementi in base ai valori della chiave primaria utilizzando le `@DynamoDbSortKey` annotazioni `@DynamoDbPartitionKey` opzionali definite nella classe di dati.

Il `query()` metodo richiede un valore di chiave di partizione e accetta facoltativamente le condizioni della chiave di ordinamento per perfezionare ulteriormente i risultati. Come l'`scan`API, le query restituiscono un `PageIterable` per le chiamate sincrone e un per le chiamate asincrone. `PagePublisher`

### `Query`esempi di metodi
<a name="ddb-en-client-use-multirecord-query-example"></a>

L'esempio di codice del `query()` metodo che segue utilizza la `MovieActor` classe. La classe di dati definisce una chiave primaria composita composta dall'**`movie`**attributo come chiave di partizione e dall'**`actor`**attributo come chiave di ordinamento. 

#### Classe `MovieActor`
<a name="ddb-en-client-use-movieactor-class"></a>

```
package org.example.tests.model;

import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbAttribute;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondaryPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondarySortKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey;

import java.util.Objects;

@DynamoDbBean
public class MovieActor implements Comparable<MovieActor> {

    private String movieName;
    private String actorName;
    private String actingAward;
    private Integer actingYear;
    private String actingSchoolName;

    @DynamoDbPartitionKey
    @DynamoDbAttribute("movie")
    public String getMovieName() {
        return movieName;
    }

    public void setMovieName(String movieName) {
        this.movieName = movieName;
    }

    @DynamoDbSortKey
    @DynamoDbAttribute("actor")
    public String getActorName() {
        return actorName;
    }

    public void setActorName(String actorName) {
        this.actorName = actorName;
    }

    @DynamoDbSecondaryPartitionKey(indexNames = "acting_award_year")
    @DynamoDbAttribute("actingaward")
    public String getActingAward() {
        return actingAward;
    }

    public void setActingAward(String actingAward) {
        this.actingAward = actingAward;
    }

    @DynamoDbSecondarySortKey(indexNames = {"acting_award_year", "movie_year"})
    @DynamoDbAttribute("actingyear")
    public Integer getActingYear() {
        return actingYear;
    }

    public void setActingYear(Integer actingYear) {
        this.actingYear = actingYear;
    }

    @DynamoDbAttribute("actingschoolname")
    public String getActingSchoolName() {
        return actingSchoolName;
    }

    public void setActingSchoolName(String actingSchoolName) {
        this.actingSchoolName = actingSchoolName;
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("MovieActor{");
        sb.append("movieName='").append(movieName).append('\'');
        sb.append(", actorName='").append(actorName).append('\'');
        sb.append(", actingAward='").append(actingAward).append('\'');
        sb.append(", actingYear=").append(actingYear);
        sb.append(", actingSchoolName='").append(actingSchoolName).append('\'');
        sb.append('}');
        return sb.toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        MovieActor that = (MovieActor) o;
        return Objects.equals(movieName, that.movieName) && Objects.equals(actorName, that.actorName) && Objects.equals(actingAward, that.actingAward) && Objects.equals(actingYear, that.actingYear) && Objects.equals(actingSchoolName, that.actingSchoolName);
    }

    @Override
    public int hashCode() {
        return Objects.hash(movieName, actorName, actingAward, actingYear, actingSchoolName);
    }

    @Override
    public int compareTo(MovieActor o) {
        if (this.movieName.compareTo(o.movieName) != 0){
            return this.movieName.compareTo(o.movieName);
        } else {
            return this.actorName.compareTo(o.actorName);
        }
    }
}
```

Gli esempi di codice che seguono eseguono una query sui seguenti elementi.

#### Elementi nella `MovieActor` tabella
<a name="ddb-en-client-use-movieactor-items"></a>

```
MovieActor{movieName='movie01', actorName='actor0', actingAward='actingaward0', actingYear=2001, actingSchoolName='null'}
MovieActor{movieName='movie01', actorName='actor1', actingAward='actingaward1', actingYear=2001, actingSchoolName='actingschool1'}
MovieActor{movieName='movie01', actorName='actor2', actingAward='actingaward2', actingYear=2001, actingSchoolName='actingschool2'}
MovieActor{movieName='movie01', actorName='actor3', actingAward='actingaward3', actingYear=2001, actingSchoolName='null'}
MovieActor{movieName='movie01', actorName='actor4', actingAward='actingaward4', actingYear=2001, actingSchoolName='actingschool4'}
MovieActor{movieName='movie02', actorName='actor0', actingAward='actingaward0', actingYear=2002, actingSchoolName='null'}
MovieActor{movieName='movie02', actorName='actor1', actingAward='actingaward1', actingYear=2002, actingSchoolName='actingschool1'}
MovieActor{movieName='movie02', actorName='actor2', actingAward='actingaward2', actingYear=2002, actingSchoolName='actingschool2'}
MovieActor{movieName='movie02', actorName='actor3', actingAward='actingaward3', actingYear=2002, actingSchoolName='null'}
MovieActor{movieName='movie02', actorName='actor4', actingAward='actingaward4', actingYear=2002, actingSchoolName='actingschool4'}
MovieActor{movieName='movie03', actorName='actor0', actingAward='actingaward0', actingYear=2003, actingSchoolName='null'}
MovieActor{movieName='movie03', actorName='actor1', actingAward='actingaward1', actingYear=2003, actingSchoolName='actingschool1'}
MovieActor{movieName='movie03', actorName='actor2', actingAward='actingaward2', actingYear=2003, actingSchoolName='actingschool2'}
MovieActor{movieName='movie03', actorName='actor3', actingAward='actingaward3', actingYear=2003, actingSchoolName='null'}
MovieActor{movieName='movie03', actorName='actor4', actingAward='actingaward4', actingYear=2003, actingSchoolName='actingschool4'}
```

Il codice seguente definisce due `QueryConditional` istanze: `keyEqual` (dopo la riga di commento 1) e `sortGreaterThanOrEqualTo` (dopo la riga di commento 1a).

#### Interroga gli elementi per chiave di partizione
<a name="keyEqual-query-conditional-example"></a>

L'`keyEqual`istanza abbina gli elementi con un valore della chiave di partizione pari a. **`movie01`** 

Questo esempio definisce anche un'espressione di filtro dopo la riga di commento 2 che filtra qualsiasi elemento che non ha un **`actingschoolname`**valore.

`QueryEnhancedRequest`Combina la condizione chiave e l'espressione di filtro per la query.

```
    public static void query(DynamoDbTable movieActorTable) {

        // 1. Define a QueryConditional instance to return items matching a partition value.
        QueryConditional keyEqual = QueryConditional.keyEqualTo(b -> b.partitionValue("movie01"));
        // 1a. Define a QueryConditional that adds a sort key criteria to the partition value criteria.
        QueryConditional sortGreaterThanOrEqualTo = QueryConditional.sortGreaterThanOrEqualTo(b -> b.partitionValue("movie01").sortValue("actor2"));
        // 2. Define a filter expression that filters out items whose attribute value is null.
        final Expression filterOutNoActingschoolname = Expression.builder().expression("attribute_exists(actingschoolname)").build();

        // 3. Build the query request.
        QueryEnhancedRequest tableQuery = QueryEnhancedRequest.builder()
                .queryConditional(keyEqual)
                .filterExpression(filterOutNoActingschoolname)
                .build();
        // 4. Perform the query using the "keyEqual" conditional and filter expression.
        PageIterable<MovieActor> pagedResults = movieActorTable.query(tableQuery);
        logger.info("page count: {}", pagedResults.stream().count()); // Log  number of pages.

        pagedResults.items().stream()
                .sorted()
                .forEach(
                        item -> logger.info(item.toString()) // Log the sorted list of items.
                );
```

**Example — Emissione utilizzando l'`keyEqual`interrogazione condizionale**  
Di seguito è riportato l'output dell'esecuzione del metodo. L'output mostra gli elementi con un `movieName` valore di **movie01** e non visualizza alcun elemento `actingSchoolName` uguale a. **`null`**  

```
2023-03-05 13:11:05 [main] INFO  org.example.tests.QueryDemo:46 - page count: 1
2023-03-05 13:11:05 [main] INFO  org.example.tests.QueryDemo:51 - MovieActor{movieName='movie01', actorName='actor1', actingAward='actingaward1', actingYear=2001, actingSchoolName='actingschool1'}
2023-03-05 13:11:05 [main] INFO  org.example.tests.QueryDemo:51 - MovieActor{movieName='movie01', actorName='actor2', actingAward='actingaward2', actingYear=2001, actingSchoolName='actingschool2'}
2023-03-05 13:11:05 [main] INFO  org.example.tests.QueryDemo:51 - MovieActor{movieName='movie01', actorName='actor4', actingAward='actingaward4', actingYear=2001, actingSchoolName='actingschool4'}
```

#### Interroga gli elementi per chiave di partizione e chiave di ordinamento
<a name="sort-type-query-conditional-example"></a>

`sortGreaterThanOrEqualTo``QueryConditional`**Perfeziona la corrispondenza della chiave di partizione (**movie01**) aggiungendo una condizione di chiave di ordinamento per valori maggiori o uguali a actor2.**

[`QueryConditional`i metodi](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/QueryConditional.html) che iniziano con `sort` richiedono che il valore della chiave di partizione corrisponda e perfezionano ulteriormente la query mediante un confronto basato sul valore della chiave di ordinamento. `Sort`nel nome del metodo non significa che i risultati siano ordinati, ma che per il confronto verrà utilizzato un valore di chiave di ordinamento.

Nel frammento seguente, modifichiamo la richiesta di query mostrata in precedenza dopo la riga di commento 3. Questo frammento sostituisce la query condizionale «KeyEqual» con la query condizionale "sortGreaterThanOrEqualTo" definita dopo la riga di commento 1a. Il codice seguente rimuove anche l'espressione del filtro.

```
        QueryEnhancedRequest tableQuery = QueryEnhancedRequest.builder()
                .queryConditional(sortGreaterThanOrEqualTo).build();
```

**Example — Emissione utilizzando la `sortGreaterThanOrEqualTo` query condizionale**  
L'output seguente mostra i risultati dell'interrogazione. **La query restituisce gli elementi con un `movieName` valore uguale a **movie01** e solo gli elementi che hanno un `actorName` valore maggiore o uguale a actor2.** Poiché rimuoviamo il filtro, la query restituisce gli elementi che non hanno alcun valore per l'attributo. `actingSchoolName`  

```
2023-03-05 13:15:00 [main] INFO  org.example.tests.QueryDemo:46 - page count: 1
2023-03-05 13:15:00 [main] INFO  org.example.tests.QueryDemo:51 - MovieActor{movieName='movie01', actorName='actor2', actingAward='actingaward2', actingYear=2001, actingSchoolName='actingschool2'}
2023-03-05 13:15:00 [main] INFO  org.example.tests.QueryDemo:51 - MovieActor{movieName='movie01', actorName='actor3', actingAward='actingaward3', actingYear=2001, actingSchoolName='null'}
2023-03-05 13:15:00 [main] INFO  org.example.tests.QueryDemo:51 - MovieActor{movieName='movie01', actorName='actor4', actingAward='actingaward4', actingYear=2001, actingSchoolName='actingschool4'}
```