Övning – Skapa, läsa, uppdatera och ta bort NoSQL-data programmatiskt

Slutförd

Du har skapat anslutningen till Azure Cosmos DB. I den här utbildningsenheten skapar du användardokument i WebCustomers-samlingen. Därefter hämtar du dem via ID, ersätter dem och tar bort dem.

Arbeta programmatiskt med dokument

Data lagras i JSON-dokument i Azure Cosmos DB. Dokument kan skapas, hämtas, ersättas eller tas bort i portalen eller programmatiskt. I den här labbuppgiften fokuserar vi på programmatiska åtgärder. Azure Cosmos DB har SDK:er på klientsidan för .NET, .NET Core, Java, Node.js och Python. De har alla stöd för de här åtgärderna. I den här modulen använder vi Java SDK för att utföra CRUD-åtgärder (skapa, hämta, uppdatera och ta bort) på NoSQL-data som lagras i Azure Cosmos DB.

De viktigaste åtgärderna för Azure Cosmos DB-dokument ingår i klassen CosmosAsyncContainer:

Upsert skapar eller byter ut beroende på om dokumentet redan finns.

För att utföra dessa åtgärder kommer du behöva hjälpklasser (POJO-klasser för Java) som representerar de objekt som lagras i databasen. Eftersom vi arbetar med en databas med användare bör du ha en User-klass som representerar användarentiteter. Den här klassen kommer att lagra primära data, till exempel förnamn, efternamn och användar-ID. (ID krävs eftersom det är partitionsnyckeln för att aktivera horisontell skalning.)

Varje användare har några associerade leveransinställningar och kuponger, så du vill att datatyperna ShippingPreference och CouponsUsed ska representera dessa entiteter. Slutligen kan varje användare ha en viss orderhistorik som kan vara obegränsad. Därför behöver du ha separata OrderHistory-entiteter med en motsvarande POJO-klass för Java.

Gå till src/main/java/com/azure/azure-cosmos-java-sql-app-mslearn och titta i mappen datatypes. Du ser flera POJO: User, ShippingPreference, OrderHistory och CouponsUsed. Vi har alltså angett alla entitets-POJO och deras hjälpklasser!

Nästa steg blir att skapa några entiteter och utföra vissa grundläggande CRUD-åtgärder på Azure Cosmos DB-containern samt de dokument som den innehåller. Du kan skicka Azure Cosmos DB som en Jackson ObjectNode-instans som direkt anger JSON-dokumentet. Men Azure Cosmos DB kan även serialisera Java-POJO till JSON. Vi rekommenderar den metoden eftersom den i allmänhet är enklast (om allt annat är lika).

Skapa dokument

  1. Öppna User.java och granska innehållet. Den bör se ut ungefär så här:

    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    import java.util.List;
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class User {
    
        /** Document ID (required by Azure Cosmos DB). */
        private String id;
    
        /** User ID. */
        private String userId;
    
        /** User last name. */
        private String lastName;
    
        /** User first name. */
        private String firstName;
    
        /** User email address. */
        private String email;
    
        /** User dividend setting. */
        private String dividend;
    
        /** User shipping preferences. */
        private ShippingPreference shippingPreference;
    
        /** User order history. */
        private List<OrderHistory> orderHistory;
    
        /** Coupons recorded by the user. */
        private List<CouponsUsed> coupons;
    }
    

    Observera att åtkomstmetoderna för fälten id, userId och så vidare är implicita (inte definierade i kod). Det här beteendet är möjligt eftersom vi använder Project Lombok @Data-annoteringen för att skapa dem automatiskt.

    @NoArgsConstructor-annoteringen kommer att generera en konstruktor utan argument som anger standardvärden för fält. @AllArgsConstructor-annoteringen genererar en annan konstruktor med en fullständig uppsättning argument för att ange alla fältvärden direkt.

    Observera att User har en id-egenskap. Alla Azure Cosmos DB-dokument kräver en id-egenskap och därför måste alla POJO som vi ska serialisera till JSON-dokument ha ett id-fält.

  2. Lägg till följande metod i CosmosApp.java:

    /**
     * Take in list of Java POJOs, check if each exists, and if not insert it.
     * @param users List of User POJOs to insert.
     */
    private static void createUserDocumentsIfNotExist(final List<User> users) {
        Flux.fromIterable(users).flatMap(user -> {
            try {
                container.readItem(user.getId(), new PartitionKey(user.getUserId()), User.class).block();
                logger.info("User {} already exists in the database", user.getId());
                return Mono.empty();
            } catch (Exception err) {
                logger.info("Creating User {}", user.getId());
                return container.createItem(user, new PartitionKey(user.getUserId()), new CosmosItemRequestOptions());
            }
        }).blockLast();
    }
    
  3. Gå sedan tillbaka till basicOperations-metoden och lägg till följande i slutet av den metoden, föreclient.close()-anropet.

    User maxaxam = new User(
        "1",
        "maxaxam",
        "Axam",
        "Max",
        "maxaxam@contoso.com",
        "2.0",
        new ShippingPreference(
            1,
            "90 W 8th St",
            "",
            "New York",
            "NY",
            "10001",
            "USA"
        ),
        new ArrayList<OrderHistory>(Arrays.asList(
            new OrderHistory(
                "3",
                "1000",
                "08/17/2018",
                "52.49"
            )
        )),
        new ArrayList<CouponsUsed>(Arrays.asList(
            new CouponsUsed(
                "A7B89F"
            )
        ))
    );
    
    User nelapin = new User(
            "2",
            "nelapin",
            "Pindakova",
            "Nela",
            "nelapin@contoso.com",
            "8.50",
            new ShippingPreference(
                1,
                "505 NW 5th St",
                "",
                "New York",
                "NY",
                "10001",
                "USA"
            ),
            new ArrayList<OrderHistory>(Arrays.asList(
                new OrderHistory(
                    "4",
                    "1001",
                    "08/17/2018",
                    "105.89"
                )
            )),
            new ArrayList<CouponsUsed>(Arrays.asList(
                new CouponsUsed(
                    "Fall 2018"
                )
            ))
    );
    
    createUserDocumentsIfNotExist(new ArrayList<User>(Arrays.asList(maxaxam, nelapin)));
    
  4. Kompilera och kör CosmosApp.java i IDE eller kör programmet i terminalen med hjälp av:

    mvn clean package
    mvn exec:java -Dexec.mainClass="com.azure.cosmos.examples.mslearnbasicapp.CosmosApp"
    

    Terminalen visar utdata efter hand som programmet skapar varje nytt användardokument.

    INFO: Database and container validation complete
    INFO: Creating User 1
    INFO: Creating User 2
    

    Det kan hända att viss ytterligare text visas av loggaren, till exempel tidsstämplar.

Gratulerar! Du har skapat dina första data i Azure Cosmos DB från ett Java-program. Vi stannar en stund och går igenom vad du har åstadkommit.

I basicOperations finns det tre nya åtgärder:

  1. Skapa maxaxam-instansenUser.
  2. Skapa nelapin-instansenUser.
  3. Anropa createUserDocumentsIfNotExist, skicka in maxaxam och nelapin i en lista.

När createUserDocumentsIfNotExist anropas infogas båda User-instanserna som objekt/dokument i Azure Cosmos DB. Avsikten med att skicka in User-instanserna som en lista är att modellera en effektiv metod för snabb inmatning av POJO i Azure Cosmos DB med minimala beräkningsresurser. createUserDocumentsIfNotExist implementerar effektiv asynkron infogning av en lista med POJO.

Anta att vårt mål är att maximera begäranden per sekund per tråd. Som jämförelse är synkroniseringsmetoden för att skriva createUserDocumentsIfNotExist – om vi bortser från readItem-kontrollen för tillfället – att iterera över varje User-instans i users. För varje Userugör vi ett blockerande anrop till createItem:

container.createItem(u, new PartitionKey(u.getUserId()), new CosmosItemRequestOptions()).block(); // <= Note the .block() which loops until request response.

Den här synkroniseringsstilen implementerar en intuitiv process: utfärda begäran, vänta på svar, utfärda nästa begäran. Däremot använder inte createUserDocumentsIfNotExist den här metoden eftersom blockerande anrop i princip slösar CPU-cykler under svarstiden för begäran, vilket leder till en låg frekvens av begäranden per sekund.

Du kan kringgå problemet med begäranden per sekund genom att skapa flera trådar i syfte att göra parallella blockerande begärandeanrop. De olika trådarna ger en förbättring av körningstiden. Men om målet är att vara sparsam med trådresurser är det här fortfarande onödigt. Varje tråd spelar upp en slinga under en begärans svarstid när den i stället skulle kunna multitaska med något annat, vilket ger dig ett lågt antal begäranden/sekund och tråd.

Av den anledningen, och i syfte att demonstrera trådeffektiv infogning av Java-POJO, har vi i stället tillhandahållit ett asynkront exempel på dokumentinfogning. Asynkront stöd i Azure Cosmos DB Java SDK v4 kommer från Project Reactor, ett Java-programramverk som tillhandahåller en strömbaserad programmeringsmodell för deklarativt dataflöde. Den används för asynkron händelsedriven programmering. createDocumentsIfNotExist implementerar asynkron programmering med Project Reactor.

I createUserDocumentsIfNotExist är Flux.fromIterable(users) en fabriksmetod i Project Reactor. Den skapar en Flux-instans som är en källa till asynkrona händelser. I det här fallet innehåller varje asynkron händelse ett User-instansargument. Flux-instansen innehåller två sådana händelser, en för maxaxam och en för nelapin. Koden inuti .flatMap( ... ).blockLast(); definierar en pipeline med sekventiella åtgärder som ska utföras på de händelser som genereras av Flux-instansen.

En av dessa åtgärder är createItem. Idén är att den här pipelinen är nästan identisk med den synkrona implementeringen, förutom att vi inte blockerar vid createItem-anropet. Mer specifikt prenumererar anropet påblockLast() den monterade pipelinen, vilket gör att de Flux två händelserna asynkront genereras. Sedan behandlar pipelinen i .flatMap( ... ).blockLast(); varje händelse på ett pseudoparallellt sätt. När en begäran utfärdas och väntar på ett svar bearbetar Project Reactor andra begäranden i bakgrunden, vilket är den viktigaste faktorn vad gäller att maximera begäranden per sekund per tråd.

0Nu när vi har demonstrerat effektiva asynkrona databasbegäranden med Project Reactor använder vi för enkelhetens skull blockerande (synkrona) anrop i resten av labbuppgiften. Om du vill läsa mer om Project Reactor kan du läsa Guiden till reaktormönster för Azure Cosmos DB.

Läsa dokument

  1. Om du vill läsa dokument från databasen lägger du till följande metod i CosmosApp:

    /**
     * Take in a Java POJO argument, extract ID and partition key, and read the corresponding document from the container.
     * In this case the ID is the partition key.
     * @param user User POJO to pull ID and partition key from.
     */
    private static CosmosItemResponse<User> readUserDocument(final User user) {
        CosmosItemResponse<User> userReadResponse = null;
    
        try {
            userReadResponse = container.readItem(user.getId(), new PartitionKey(user.getUserId()), User.class).block();
            logger.info("Read user {}", user.getId());
        } catch (CosmosException de) {
            logger.error("Failed to read user {}", user.getId(), de);
        }
    
        return userReadResponse;
    }
    
  2. Kopiera och klistra in följande kod i slutet av metoden basicOperations, efter koden för dokumentskapande:

    readUserDocument(maxaxam);
    
  3. Kompilera och kör CosmosApp.java i IDE eller kör programmet i terminalen med hjälp av:

    mvn clean package
    mvn exec:java -Dexec.mainClass="com.azure.cosmos.examples.mslearnbasicapp.CosmosApp"
    

    Terminalen visar följande utdata, där ”Read user 1” innebär att dokumentet hämtades.

    INFO: Database and container validation complete
    INFO: User 1 already exists in the database
    INFO: User 2 already exists in the database
    INFO: Read user 1
    

    Det kan hända att viss ytterligare text visas av loggaren.

Ersätta dokument

Azure Cosmos DB har stöd för ersättning av JSON-dokument. I det här fallet ska vi uppdatera en användarpost eftersom efternamnet har ändrats.

  1. Lägg till replaceUserDocument-metoden efter readUserDocument-metoden i CosmosApp.java-filen.

    /**
     * Take in a Java POJO argument, extract ID and partition key,
     * and replace the existing document with the same ID and partition key to match.
     * @param user User POJO representing the document update.
     */
    private static void replaceUserDocument(final User user) {
        try {
            CosmosItemResponse<User> userReplaceResponse = container.replaceItem(user, user.getId(), new PartitionKey(user.getUserId())).block();
            logger.info("Replaced User {}", user.getId());
        } catch (CosmosException de) {
            logger.error("Failed to replace User {}", user.getUserId());
        }
    }
    
  2. Kopiera och klistra in följande kod i slutet av basicOperations metoden efter dokumentets läskod.

    maxaxam.setLastName("Suh");
    replaceUserDocument(maxaxam);
    
  3. Kompilera och kör CosmosApp.java i IDE eller kör programmet i terminalen med hjälp av:

    mvn clean package
    mvn exec:java -Dexec.mainClass="com.azure.cosmos.examples.mslearnbasicapp.CosmosApp"
    

    Du ser följande utdata i terminalen, och ”Replaced last name for Suh” innebär att dokumentet ersattes.

    INFO: Database and container validation complete
    INFO: User 1 already exists in the database
    INFO: User 2 already exists in the database
    INFO: Read user 1
    INFO: Replaced last name for Suh
    

Ta bort dokument

  1. Kopiera och klistra in metoden deleteUserDocument under replaceUserDocument-metoden.

    /**
     * Take in a Java POJO argument, extract ID and partition key,
     * and delete the corresponding document.
     * @param user User POJO representing the document update.
     */
    private static void deleteUserDocument(final User user) {
        try {
            container.deleteItem(user.getId(), new PartitionKey(user.getUserId())).block();
            logger.info("Deleted user {}", user.getId());
        } catch (CosmosException de) {
            logger.error("User {} could not be deleted.", user.getId());
        }
    }
    
  2. Kopiera och klistra in följande kod i slutet av basicOperations-metoden.

    deleteUserDocument(maxaxam);
    
  3. Kompilera och kör CosmosApp.java i IDE eller kör programmet i terminalen med hjälp av:

    mvn clean package
    mvn exec:java -Dexec.mainClass="com.azure.cosmos.examples.mslearnbasicapp.CosmosApp"
    

    Du ser följande utdata i terminalen, och ”Deleted user 1” innebär att dokumentet togs bort.

    INFO: Database and container validation complete
    INFO: User 1 already exists in the database
    INFO: User 2 already exists in the database
    INFO: Read User 1
    INFO: Replaced last name for Suh
    INFO: Deleted User 1
    

Arbeta programmatiskt med dokument

Data lagras i JSON-dokument i Azure Cosmos DB. Dokument kan skapas, hämtas, ersättas eller tas bort i portalen eller programmatiskt. I den här labbuppgiften fokuserar vi på programmatiska åtgärder. Alla dessa åtgärder är tillgängliga i Azure Cosmos DB Java SDK och är också tillgängliga via Spring Data-programmeringsmodellen. I den här modulen använder vi Azure Cosmos DB för Spring Data för att utföra CRUD-åtgärder (skapa, hämta, uppdatera och ta bort) på NoSQL-data som lagras i Azure Cosmos DB.

Huvudåtgärderna för dokument i Azure Cosmos DB för Spring Data är grundläggande åtgärder i programmeringsmodellen Spring Data:

  • save – punkt-skriv eller -uppdatera ett dokument, beroende på om dokumentet redan finns.
  • view – punkt-läs ett dokument
  • delete – punkt-ta bort ett dokument

För att utföra dessa åtgärder kommer du behöva hjälpklasser (POJO-klasser för Java) som representerar de objekt som lagras i databasen. Eftersom vi arbetar med en databas med onlinekunder kommer du att vilja använda klassen WebCustomer för att representera användarentiteter. Den här klassen kommer att lagra primära data, till exempel förnamn, efternamn och användar-ID. (ID krävs eftersom det är partitionsnyckeln för att aktivera horisontell skalning.)

Varje webbkund har vissa associerade leveransinställningar och kuponger, så du vill att datatyperna ShippingPreference och CouponsUsed ska representera dessa entiteter. Slutligen kan varje webbkund ha en viss orderhistorik som potentiellt kan vara obegränsad. Därför behöver du ha separata OrderHistory-entiteter med en motsvarande POJO-klass för Java.

Gå till src/main/java/com/azure/cosmos/examples/springexamples. POJO för WebCustomer visas. Titta nu i mappen common. Du kommer att se flera POJO: ShippingPreference, OrderHistory och CouponsUsed. Vi har alltså angett alla entitets-POJO och deras hjälpklasser!

Nästa steg blir att skapa några entiteter och utföra vissa grundläggande CRUD-åtgärder på Azure Cosmos DB-containern samt de dokument som den innehåller. Du kan skicka Azure Cosmos DB som en Jackson ObjectNode-instans som direkt anger JSON-dokumentet. Men Azure Cosmos DB kan även serialisera Java-POJO till JSON. Vi rekommenderar den metoden eftersom den i allmänhet är enklast (om allt annat är lika).

Skapa och uppdatera dokument

  1. Öppna WebCustomer.java och granska innehållet. Den bör se ut ungefär så här:

    // Copyright (c) Microsoft Corporation. All rights reserved.
    // Licensed under the MIT License.
    package com.azure.cosmos.examples.springexamples;
    
    import com.azure.cosmos.examples.springexamples.common.CouponsUsed;
    import com.azure.cosmos.examples.springexamples.common.OrderHistory;
    import com.azure.cosmos.examples.springexamples.common.ShippingPreference;
    import com.azure.spring.data.cosmos.core.mapping.Container;
    import com.azure.spring.data.cosmos.core.mapping.PartitionKey;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    import java.util.List;
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Container(containerName = "WebCustomer", ru = "400")
    public class WebCustomer {
    
        /** Document ID (required by Azure Cosmos DB). */
        private String id;
    
        /** WebCustomer ID. */
        private String userId;
    
        /** WebCustomer last name. */
        @PartitionKey
        private String lastName;
    
        /** WebCustomer first name. */
        private String firstName;
    
        /** WebCustomer email address. */
        private String email;
    
        /** WebCustomer dividend setting. */
        private String dividend;
    
        /** WebCustomer shipping preferences. */
        private ShippingPreference shippingPreference;
    
        /** WebCustomer order history. */
        private List<OrderHistory> orderHistory;
    
        /** Coupons recorded by the user. */
        private List<CouponsUsed> coupons;
    }
    

    Observera att åtkomstmetoderna för fälten id, userId och så vidare är implicita (inte definierade i kod). Det här beteendet är möjligt eftersom vi använder Project Lombok @Data-annoteringen för att skapa dem automatiskt.

    @NoArgsConstructor-annoteringen kommer att generera en konstruktor utan argument som anger standardvärden för fält. @AllArgsConstructor-annoteringen genererar en annan konstruktor med en fullständig uppsättning argument för att ange alla fältvärden direkt.

    Observera att WebCustomer har en id-egenskap. Alla Azure Cosmos DB-dokument kräver en id-egenskap och därför måste alla POJO som vi ska serialisera till JSON-dokument ha ett id-fält.

  2. Lägg till följande metod i CosmosSample.java:

    /**
     * Take in list of Java POJOs and insert them into the database.
     * @param webCustomers List of WebCustomer POJOs to insert.
     */
    private void createWebCustomerDocumentsIfNotExist(final List<WebCustomer> webCustomers) {
        Flux.fromIterable(webCustomers).flatMap(webCustomer -> {
            logger.info("Creating WebCustomer {}", webCustomer.getId());
            return this.reactiveWebCustomerRepository.save(webCustomer);
        }).blockLast();
    }
    
  3. Hitta run-metoden och lägg till nedanstående kod i slutet av metoden.

    WebCustomer maxaxam = new WebCustomer(
            "1",
            "maxaxam",
            "Axam",
            "Max",
            "maxaxam@contoso.com",
            "2.0",
            new ShippingPreference(
                    1,
                    "90 W 8th St",
                    "",
                    "New York",
                    "NY",
                    "10001",
                    "USA"
            ),
            new ArrayList<OrderHistory>(Arrays.asList(
                    new OrderHistory(
                            "3",
                            "1000",
                            "08/17/2018",
                            "52.49"
                    )
            )),
            new ArrayList<CouponsUsed>(Arrays.asList(
                    new CouponsUsed(
                            "A7B89F"
                    )
            ))
    );
    
    WebCustomer nelapin = new WebCustomer(
            "2",
            "nelapin",
            "Pindakova",
            "Nela",
            "nelapin@contoso.com",
            "8.50",
            new ShippingPreference(
                    1,
                    "505 NW 5th St",
                    "",
                    "New York",
                    "NY",
                    "10001",
                    "USA"
            ),
            new ArrayList<OrderHistory>(Arrays.asList(
                    new OrderHistory(
                            "4",
                            "1001",
                            "08/17/2018",
                            "105.89"
                    )
            )),
            new ArrayList<CouponsUsed>(Arrays.asList(
                    new CouponsUsed(
                            "Fall 2018"
                    )
            ))
    );
    
    createWebCustomerDocumentsIfNotExist(new ArrayList(Arrays.asList(maxaxam, nelapin)));
    
  4. Kompilera och kör CosmosSample.java i IDE eller kör programmet i terminalen med hjälp av:

    mvn clean package
    mvn spring-boot:run
    

    Du bör se följande i dina terminalutdata:

    INFO: Creating WebCustomer 1
    INFO: Creating WebCustomer 2
    

Gratulerar! Du har skapat och/eller uppdaterat dina första data i Azure Cosmos DB från ett Java-program. Vi stannar en stund och går igenom vad du har åstadkommit.

I run finns det tre nya åtgärder:

  1. Skapa/uppdatera maxaxam-instansenWebCustomer.
  2. Skapa/uppdatera nelapin-instansenWebCustomer.
  3. Anropa createWebCustomerDocumentsIfNotExist, skicka in maxaxam och nelapin i en lista.

När createWebCustomerDocumentsIfNotExist anropas infogas båda WebCustomer-instanserna som objekt/dokument i Azure Cosmos DB. Avsikten med att skicka in WebCustomer-instanserna som en lista är att modellera en effektiv metod för snabb inmatning av POJO i Azure Cosmos DB med minimala beräkningsresurser. createWebCustomerDocumentsIfNotExist implementerar effektiv asynkron infogning av en lista med POJO. Om något av dokumenten redan finns, kommer save att utföra en uppdatering i stället för att skapa ett dokument.

Anta att vårt mål är att maximera begäranden per sekund per tråd. Som jämförelse är synkroniseringsmetoden för att skriva createWebCustomerDocumentsIfNotExist att iterera över varje WebCustomer-instans i webCustomers. För varje WebCustomerwebCustomergör vi ett blockerande anrop till save:

this.reactiveWebCustomerRepository.save(webCustomer).block(); // <= Note the .block() which loops until request response.

Den här synkroniseringsstilen implementerar en intuitiv process: utfärda begäran, vänta på svar, utfärda nästa begäran. Däremot använder inte createWebCustomerDocumentsIfNotExist den här metoden eftersom blockerande anrop i princip slösar CPU-cykler under svarstiden för begäran, vilket leder till en låg frekvens av begäranden per sekund.

Du kan kringgå problemet med begäranden per sekund genom att skapa flera trådar i syfte att göra parallella blockerande begärandeanrop. De olika trådarna ger en förbättring av körningstiden. Men om målet är att vara sparsam med trådresurser är det här fortfarande onödigt. Varje tråd spelar upp en slinga under en begärans svarstid när den i stället skulle kunna multitaska med något annat, vilket ger dig ett lågt antal begäranden/sekund och tråd.

Av den anledningen, och i syfte att demonstrera trådeffektiv infogning av Java-POJO, har vi i stället tillhandahållit ett asynkront exempel på dokumentinfogning. Asynkront stöd i Spring Data kommer från Project Reactor, ett Java-programramverk som tillhandahåller en streamingbaserad programmeringsmodell för deklarativt dataflöde för asynkron händelsedriven programmering. createWebCustomerDocumentsIfNotExist implementerar asynkron programmering med Project Reactor.

I createWebCustomerDocumentsIfNotExist är Flux.fromIterable(webCustomers) en fabriksmetod i Project Reactor. Den skapar en Flux-instans som är en källa till asynkrona händelser. I det här fallet innehåller varje asynkron händelse ett WebCustomer-instansargument. Flux-instansen innehåller två sådana händelser, en för maxaxam och en för nelapin. Koden inuti .flatMap( ... ).blockLast(); definierar en pipeline med sekventiella åtgärder som ska utföras på de händelser som genereras av Flux-instansen.

I det här fallet är de två åtgärderna i pipelinen save-anrop. Idén är att den här pipelinen är nästan identisk med den synkrona implementeringen, förutom att vi inte blockerar vid save-anropet. Mer specifikt prenumererar anropet påblockLast() den monterade pipelinen, vilket gör att de Flux två händelserna asynkront genereras. Sedan behandlar pipelinen i .flatMap( ... ).blockLast(); varje händelse på ett pseudoparallellt sätt. När en begäran utfärdas och väntar på ett svar bearbetar Project Reactor andra begäranden i bakgrunden, vilket är den viktigaste faktorn vad gäller att maximera begäranden per sekund per tråd.

Nu när vi har demonstrerat effektiva asynkrona databasbegäranden med Project Reactor, använder vi för enkelhetens skull blockerande asynkrona anrop (i realiteten synkrona anrop) i resten av labbuppgiften. Om du vill läsa mer om Project Reactor kan du läsa Guiden till reaktormönster för Azure Cosmos DB.

Läsa dokument

  1. Om du vill läsa dokument från databasen lägger du till följande metod i CosmosSample:

    /**
     * Take in a Java POJO argument, extract ID and partition key, and read the corresponding document from the container.
     * In this case the ID is the partition key.
     * @param webCustomer User POJO to pull ID and partition key from.
     */
    private WebCustomer readWebCustomerDocument(final WebCustomer webCustomer) {
        WebCustomer webCustomerResult = null;
    
        try {
            logger.info("Read webCustomer {}", webCustomer.getId());
            webCustomerResult = this.reactiveWebCustomerRepository.findById(webCustomer.getId(), new PartitionKey(webCustomer.getLastName())).block();
        } catch (CosmosException de) {
            logger.error("Failed to read webCustomer {}", webCustomer.getId(), de);
        }
    
        return webCustomer;
    }
    
  2. Kopiera och klistra in följande kod i slutet av metoden run, efter koden för dokumentskapande:

    readWebCustomerDocument(maxaxam);
    
  3. Kompilera och kör CosmosSample.java i IDE eller kör programmet i terminalen med hjälp av:

    mvn clean package
    mvn spring-boot:run
    

    Du bör se följande i dina terminalutdata: ”Read user 1” anger att dokumentet hämtades.

    INFO: Read webCustomer 1
    

Ta bort dokument

  1. Kopiera och klistra in metoden deleteWebCustomerDocument under readWebCustomerDocument-metoden.

    /**
     * Take in a Java POJO argument, extract ID and partition key,
     * and delete the corresponding document.
     * @param webCustomer User POJO representing the document update.
     */
    private void deleteWebCustomerDocument(final WebCustomer webCustomer) {
        try {
            this.reactiveWebCustomerRepository.deleteById(webCustomer.getId(),new PartitionKey(webCustomer.getLastName())).block();
            logger.info("Deleted webCustomer {}", webCustomer.getId());
        } catch (CosmosException de) {
            logger.error("User {} could not be deleted.", webCustomer.getId());
        }
    }
    
  2. Kopiera och klistra in följande kod i slutet av run-metoden.

    deleteWebCustomerDocument(maxaxam);
    
  3. Kompilera och kör CosmosSample.java i IDE eller kör programmet i terminalen med hjälp av:

    mvn clean package
    mvn spring-boot:run
    

    Du bör se följande i dina terminalutdata: ”Deleted user 1” anger att dokumentet har tagits bort.

    INFO: Deleted webCustomer 1
    

I den här lektionen har du skapat, uppdaterat, läst och tagit bort dokument i din Azure Cosmos DB-databas.