Ejercicio: creación, lectura, actualización y eliminación de datos NoSQL mediante programación

Completado

Ha realizado la conexión a Azure Cosmos DB. En esta unidad, creará documentos de usuario en su colección WebCustomers. Luego, recuperará los documentos por identificador, los reemplazará y los eliminará.

Trabajo con documentos mediante programación

Los datos se almacenan en documentos JSON en Azure Cosmos DB. Se pueden crear, recuperar, reemplazar o eliminar documentos en el portal o mediante programación. Este laboratorio se centra en las operaciones de programación. Azure Cosmos DB proporciona SDK del lado cliente para .NET, .NET Core, Java, Node.js y Python, cada uno de los cuales admite estas operaciones. En este módulo usaremos el SDK de Java para llevar a cabo operaciones CRUD (crear, recuperar, actualizar y eliminar) en los datos NoSQL almacenados en Azure Cosmos DB.

Las operaciones principales para documentos de Azure Cosmos DB forman parte de la clase CosmosAsyncContainer:

Upsert realiza una operación de crear o reemplazar en función de si el documento ya existe.

Para realizar cualquiera de estas operaciones, necesitará clases auxiliares (clases POJO de Java) que representen los objetos almacenados en la base de datos. Dado que estamos trabajando con una base de datos de usuarios, querrá tener una clase User que represente entidades de usuario. Esta clase almacenará los datos principales, como el nombre, el apellido y el identificador de usuario. (El identificador es obligatorio porque es la clave de partición para habilitar el escalado horizontal).

Cada usuario tiene algunas preferencias de envío y cupones asociados, por lo que querrá que los tipos de datos ShippingPreference y CouponsUsed representen esas entidades. Por último, puede que cada usuario tenga algún historial de pedidos que sea potencialmente ilimitado, por lo que querrá tener entidades OrderHistory independientes con la clase POJO de Java correspondiente.

Vaya a src/main/java/com/azure/azure-cosmos-java-sql-app-mslearn y mire en la carpeta datatypes. Verá varias clases POJO: User, ShippingPreference, OrderHistory y CouponsUsed. Así que hemos proporcionado todas las clases POJO de entidad y sus clases auxiliares.

A continuación, crearemos algunas entidades y realizaremos algunas operaciones CRUD básicas en el contenedor de Azure Cosmos DB y los documentos que contiene. Puede pasar a Azure Cosmos DB una instancia ObjectNode de Jackson que especifique directamente el documento JSON. Sin embargo, Azure Cosmos DB también es capaz de serializar las clases POJO de Java en JSON, y recomendamos este enfoque como la opción más sencilla cuando todo lo demás sea igual.

Creación de documentos

  1. Abra User.java y examine su contenido. Debe tener el siguiente aspecto:

    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;
    }
    

    Observe que los métodos de acceso para los campos id y userId (y otros) son implícitos (no se definen en el código). Este comportamiento es posible porque usamos el proyecto de anotación @Data de Lombok para crearlos automáticamente.

    La anotación @NoArgsConstructor generará un constructor sin argumentos que establece los valores de campo predeterminados. La anotación @AllArgsConstructor generará otro constructor con un conjunto completo de argumentos para especificar directamente todos los valores de campo.

    Tenga en cuenta que User tiene una propiedad id. Todos los documentos de Azure Cosmos DB requieren una propiedad id; por lo tanto, todos las clases POJO que se van a serializar en documentos JSON deben tener un campo id.

  2. Agregue el método siguiente a 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. Luego vuelva al método basicOperations y agregue lo siguiente al final de ese método, delante de la llamada a client.close().

    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. Compile y ejecute CosmosApp.java en el IDE o ejecute el programa en el terminal usando:

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

    El terminal muestra la salida cuando la aplicación crea cada nuevo documento de usuario.

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

    Es posible que vea algún texto adicional emitido por el registrador, como las marcas de tiempo.

Felicidades. Ha creado los primeros datos en Azure Cosmos DB desde una aplicación de Java. Vamos a hacer una pausa y evaluar lo que hizo aquí.

En basicOperations, hay tres acciones nuevas:

  1. Cree la instancia User de maxaxam.
  2. Cree la instancia User de nelapin.
  3. Llame a createUserDocumentsIfNotExist, pasando maxaxam y nelapin en una lista.

La llamada a createUserDocumentsIfNotExist inserta ambas instancias de User como elementos o documentos en Azure Cosmos DB. Al pasar las instancias de User en forma de lista, nuestra intención es modelar un método de rendimiento para ingerir clases POJO rápidamente en Azure Cosmos DB con el uso mínimo de recursos de proceso. createUserDocumentsIfNotExist implementa la inserción asincrónica eficaz de una lista de clases POJO.

Supongamos que nuestro objetivo es maximizar las solicitudes/segundo por subproceso. A efectos de la comparación, el enfoque sincrónico para escribir createUserDocumentsIfNotExist, que omite por un momento la comprobación de readItem, sería recorrer en iteración cada User en users. Para cada u de User, realizaremos un llamada de bloqueo a createItem:

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

Este estilo sincrónico implementa un proceso intuitivo: emitir solicitud, esperar respuesta, emitir siguiente solicitud. Sin embargo createUserDocumentsIfNotExist no emplea este enfoque, ya que las llamadas de bloqueo básicamente desperdiciarán los ciclos de la CPU durante el tiempo de respuesta de la solicitud, lo que provocará un número bajo de solicitudes/segundo.

Puede evitar este problema de solicitudes/segundo generando varios subprocesos para realizar llamadas de solicitud de bloqueo en paralelo. Los múltiples subprocesos incorporarán una mejora en tiempo de ejecución. Sin embargo, si su objetivo es ahorrar recursos de subproceso, esto sigue siendo excesivo. Cada subproceso genera bucles durante el tiempo de respuesta de la solicitud (cuando podría tener un comportamiento multitarea en otra cosa), lo que se traducirá en un número bajo de solicitudes/segundo por subproceso.

Por esta razón, y con el fin de mostrar la inserción eficaz por subproceso de clases POJO de Java, en su lugar, ofrecemos un ejemplo asincrónico de inserción de documentos. La compatibilidad asincrónica del SDK de Java v4 de Azure Cosmos DB procede de Project Reactor, un marco de trabajo de la aplicación de Java que proporciona un modelo de programación de flujo de trabajo declarativo basado en secuencias para la programación orientada a eventos asincrónicos. createDocumentsIfNotExist implementa la programación asincrónica de Project Reactor.

En createUserDocumentsIfNotExist, Flux.fromIterable(users) es un Factory Method de Project Reactor. Crea una instancia de Flux que es un origen de eventos asincrónicos. En este caso, cada "evento" asincrónico incluye un argumento de instancia de User. La instancia de Flux contiene dos eventos de este tipo, uno para maxaxam y otro para nelapin. El código incluido en .flatMap( ... ).blockLast(); define una canalización de operaciones secuenciales que se realizarán en los eventos emitidos por la instancia de Flux.

Una de esas operaciones es createItem. La idea es que esta canalización es casi idéntica a la implementación sincrónica, salvo que no se bloquea en la llamada createItem. En concreto, la llamada a blockLast() se suscribe a la canalización ensamblada, lo que provoca que el objeto Flux emita de forma asincrónica sus dos eventos. Luego, la canalización dentro de .flatMap( ... ).blockLast(); procesa cada uno de esos eventos de forma pseudoparalela. Cuando se emite una solicitud y se espera una respuesta, Project Reactor procesará otras solicitudes en segundo plano, que es el factor crítico para maximizar el numero de solicitudes/segundo por subproceso.

Ahora que hemos mostrado solicitudes de base de datos asincrónicas eficaces con Project Reactor, por simplicidad, en el resto de este laboratorio se usarán llamadas de bloqueo (sincrónicas). Para más información sobre Project Reactor, eche un vistazo a la guía de patrones de Reactor de Azure Cosmos DB.

Lectura de documentos

  1. Para leer documentos de la base de datos, agregue el método siguiente a 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. Copie el código siguiente y péguelo al final del método basicOperations, después del código de creación de documentos:

    readUserDocument(maxaxam);
    
  3. Compile y ejecute CosmosApp.java en el IDE o ejecute el programa en el terminal usando:

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

    En el terminal se muestra la salida siguiente, donde "Read user 1" indica que se ha recuperado el documento.

    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
    

    Es posible que también vea texto adicional emitido por el registrador.

Reemplazo de documentos

Azure Cosmos DB admite la sustitución de documentos JSON. En este caso, vamos a actualizar un registro de usuario para aplicar un cambio en su apellido.

  1. Agregue el método replaceUserDocument después del método readUserDocument en el archivo CosmosApp. Java.

    /**
     * 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. Copie el código siguiente y péguelo al final del método basicOperations, después del código de lectura de documentos.

    maxaxam.setLastName("Suh");
    replaceUserDocument(maxaxam);
    
  3. Compile y ejecute CosmosApp.java en el IDE o ejecute el programa en el terminal usando:

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

    El terminal muestra la salida siguiente, donde "Replaced last name for Suh" indica que se ha reemplazado el documento.

    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
    

Eliminación de documentos

  1. Copie y pegue el método deleteUserDocument en el método replaceUserDocument.

    /**
     * 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. Copie y pegue el código siguiente al final del método basicOperations.

    deleteUserDocument(maxaxam);
    
  3. Compile y ejecute CosmosApp.java en el IDE o ejecute el programa en el terminal usando:

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

    En el terminal se muestra la salida siguiente, donde "Deleted user 1" indica que se ha eliminado el documento.

    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
    

Trabajo con documentos mediante programación

Los datos se almacenan en documentos JSON en Azure Cosmos DB. Se pueden crear, recuperar, reemplazar o eliminar documentos en el portal o mediante programación. Este laboratorio se centra en las operaciones de programación. Todas estas operaciones están disponibles en el SDK de Azure Cosmos DB para Java y también se puede acceder a ellas con el modelo de programación de Spring Data. En este módulo, usaremos Spring Data para Azure Cosmos DB para llevar a cabo operaciones CRUD (crear, recuperar, actualizar y eliminar) en los datos NoSQL almacenados en Azure Cosmos DB.

Las operaciones principales para los documentos de Spring Data para Azure Cosmos DB son operaciones básicas del modelo de programación de Spring Data:

  • save: apuntar y escribir o actualizar un documento, en función de si el documento ya existe.
  • view: apuntar y leer un documento
  • delete: apuntar y eliminar un documento.

Para realizar cualquiera de estas operaciones, necesitará clases auxiliares (clases POJO de Java) que representen los objetos almacenados en la base de datos. Dado que estamos trabajando con una base de datos de clientes en línea, querrá usar la clase WebCustomer que represente entidades de usuario. Esta clase almacenará los datos principales, como el nombre, el apellido y el identificador de usuario. (El identificador es obligatorio porque es la clave de partición para habilitar el escalado horizontal).

Cada cliente web tiene algunas preferencias de envío y cupones asociados, por lo que querrá que los tipos de datos ShippingPreference y CouponsUsed representen esas entidades. Por último, puede que cada cliente web tenga algún historial de pedidos que sea potencialmente ilimitado, por lo que querrá tener entidades OrderHistory independientes con una clase POJO de Java correspondiente.

Vaya a src/main/java/com/azure/cosmos/examples/springexamples. Verá la clase POJO WebCustomer. Ahora, mire en la carpeta common. Verá varias clases POJO: ShippingPreference, OrderHistory y CouponsUsed. Así que hemos proporcionado todas las clases POJO de entidad y sus clases auxiliares.

A continuación, crearemos algunas entidades y realizaremos algunas operaciones CRUD básicas en el contenedor de Azure Cosmos DB y los documentos que contiene. Puede pasar a Azure Cosmos DB una instancia ObjectNode de Jackson que especifique directamente el documento JSON. Sin embargo, Azure Cosmos DB también es capaz de serializar las clases POJO de Java en JSON, y recomendamos este enfoque como la opción más sencilla cuando todo lo demás sea igual.

Creación y actualización de documentos

  1. Abra WebCustomer.java y examine su contenido. Debe tener el siguiente aspecto:

    // 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;
    }
    

    Observe que los métodos de acceso para los campos id y userId (y otros) son implícitos (no se definen en el código). Este comportamiento es posible porque usamos el proyecto de anotación @Data de Lombok para crearlos automáticamente.

    La anotación @NoArgsConstructor generará un constructor sin argumentos que establece los valores de campo predeterminados. La anotación @AllArgsConstructor generará otro constructor con un conjunto completo de argumentos para especificar directamente todos los valores de campo.

    Tenga en cuenta que WebCustomer tiene una propiedad id. Todos los documentos de Azure Cosmos DB requieren una propiedad id; por lo tanto, todos las clases POJO que se van a serializar en documentos JSON deben tener un campo id.

  2. Agregue el método siguiente a 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. Busque el método run y agregue el siguiente código al final de ese método.

    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. Compile y ejecute CosmosSample.java en el IDE o ejecute el programa en el terminal usando:

    mvn clean package
    mvn spring-boot:run
    

    Entre las salidas del terminal, debería ver:

    INFO: Creating WebCustomer 1
    INFO: Creating WebCustomer 2
    

¡Enhorabuena! Ha creado o actualizado los primeros datos en Azure Cosmos DB desde una aplicación de Java. Vamos a hacer una pausa y evaluar lo que hizo aquí.

En run, hay tres acciones nuevas:

  1. Cree o actualice la instancia WebCustomer de maxaxam.
  2. Cree o actualice la instancia WebCustomer de nelapin.
  3. Llame a createWebCustomerDocumentsIfNotExist, pasando maxaxam y nelapin en una lista.

La llamada a createWebCustomerDocumentsIfNotExist inserta ambas instancias de WebCustomer como elementos o documentos en Azure Cosmos DB. Al pasar las instancias de WebCustomer en forma de lista, nuestra intención es modelar un método de rendimiento para ingerir clases POJO rápidamente en Azure Cosmos DB con el uso mínimo de recursos de proceso. createWebCustomerDocumentsIfNotExist implementa la inserción asincrónica eficaz de una lista de clases POJO. Si ya existe cualquiera de los documentos, save realizará una actualización en lugar de crear un documento.

Supongamos que nuestro objetivo es maximizar las solicitudes/segundo por subproceso. A efectos de la comparación, el enfoque sincrónico para escribir createWebCustomerDocumentsIfNotExist sería recorrer en iteración cada WebCustomer en webCustomers. Para cada webCustomer de WebCustomer, realizaremos un llamada de bloqueo a save:

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

Este estilo sincrónico implementa un proceso intuitivo: emitir solicitud, esperar respuesta, emitir siguiente solicitud. Sin embargo createWebCustomerDocumentsIfNotExist no emplea este enfoque, ya que las llamadas de bloqueo básicamente desperdiciarán los ciclos de la CPU durante el tiempo de respuesta de la solicitud, lo que provocará un número bajo de solicitudes/segundo.

Puede evitar este problema de solicitudes/segundo generando varios subprocesos para realizar llamadas de solicitud de bloqueo en paralelo. Los múltiples subprocesos incorporarán una mejora en tiempo de ejecución. Sin embargo, si su objetivo es ahorrar recursos de subproceso, esto sigue siendo excesivo. Cada subproceso genera bucles durante el tiempo de respuesta de la solicitud (cuando podría tener un comportamiento multitarea en otra cosa), lo que se traducirá en un número bajo de solicitudes/segundo por subproceso.

Por esta razón, y con el fin de mostrar la inserción eficaz por subproceso de clases POJO de Java, en su lugar, ofrecemos un ejemplo asincrónico de inserción de documentos. La compatibilidad asincrónica de Spring Data proviene de Project Reactor, un marco de trabajo de la aplicación de Java que proporciona un modelo de programación de flujo de trabajo declarativo basado en secuencias para la programación orientada a eventos asincrónicos. createWebCustomerDocumentsIfNotExist implementa la programación asincrónica de Project Reactor.

En createWebCustomerDocumentsIfNotExist, Flux.fromIterable(webCustomers) es un Factory Method de Project Reactor. Crea una instancia de Flux que es un origen de eventos asincrónicos. En este caso, cada "evento" asincrónico incluye un argumento de instancia de WebCustomer. La instancia de Flux contiene dos eventos de este tipo, uno para maxaxam y otro para nelapin. El código incluido en .flatMap( ... ).blockLast(); define una canalización de operaciones secuenciales que se realizarán en los eventos emitidos por la instancia de Flux.

En este caso, las dos operaciones de la canalización son llamadas a save. La idea es que esta canalización es casi idéntica a la implementación sincrónica, salvo que no se bloquea en la llamada save. En concreto, la llamada a blockLast() se suscribe a la canalización ensamblada, lo que provoca que el objeto Flux emita de forma asincrónica sus dos eventos. Luego, la canalización dentro de .flatMap( ... ).blockLast(); procesa cada uno de esos eventos de forma pseudoparalela. Cuando se emite una solicitud y se espera una respuesta, Project Reactor procesará otras solicitudes en segundo plano, que es el factor crítico para maximizar el numero de solicitudes/segundo por subproceso.

Ahora que hemos mostrado solicitudes de base de datos asincrónicas eficaces con Project Reactor, por simplicidad, en el resto de este laboratorio se usarán llamadas asincrónicas de bloqueo (llamadas de sincronización efectivas). Para más información sobre Project Reactor, eche un vistazo a la guía de patrones de Reactor de Azure Cosmos DB.

Lectura de documentos

  1. Para leer documentos de la base de datos, agregue el método siguiente a 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. Copie el código siguiente y péguelo al final del método run, después del código de creación de documentos:

    readWebCustomerDocument(maxaxam);
    
  3. Compile y ejecute CosmosSample.java en el IDE o ejecute el programa en el terminal usando:

    mvn clean package
    mvn spring-boot:run
    

    Entre las salidas del terminal, debería ver lo siguiente. "Read User 1" indica que se ha recuperado el documento.

    INFO: Read webCustomer 1
    

Eliminación de documentos

  1. Copie y pegue el método deleteWebCustomerDocument en el método readWebCustomerDocument.

    /**
     * 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. Copie y pegue el código siguiente al final del método run.

    deleteWebCustomerDocument(maxaxam);
    
  3. Compile y ejecute CosmosSample.java en el IDE o ejecute el programa en el terminal usando:

    mvn clean package
    mvn spring-boot:run
    

    Entre las salidas del terminal, debería ver lo siguiente. "Deleted user 1" indica que se ha eliminado el documento.

    INFO: Deleted webCustomer 1
    

En esta unidad, ha creado, actualizado, leído y eliminado documentos en la base de datos de Azure Cosmos DB.