Упражнение. Выполнение запросов с помощью пакета SDK Azure Cosmos DB для Java

Завершено

Итак, документы в приложении созданы, и мы можем запросить их из приложения. Пакет SDK Azure Cosmos DB для Java использует SQL-запросы. Пакет SDK для .NET обеспечивает дополнительную поддержку запросов LINQ, но в пакете SDK для Java такая поддержка отсутствует. Этот урок посвящен запуску SQL-запросов из своего приложения, а не с портала.

Для тестирования этих запросов будут использоваться документы, созданные для приложения интернет-магазина.

Выполнение запросов SQL

  1. В следующем примере показано выполнение запроса в SQL из кода Java. Скопируйте код и добавьте его в конец файла CosmosApp.java.

    /**
     * Execute a custom query on the Azure Cosmos DB container.
     * @param query Query String.
     */
    private static void executeSimpleQuery(final String query) {
    
        final int preferredPageSize = 10;
        CosmosQueryRequestOptions queryOptions = new CosmosQueryRequestOptions();
    
        CosmosPagedFlux<User> pagedFluxResponse = container.queryItems(
                query, queryOptions, User.class);
    
        logger.info("Running SQL query...");
    
        pagedFluxResponse.byPage(preferredPageSize).flatMap(fluxResponse -> {
            logger.info("Got a page of query result with " + fluxResponse.getResults().size()
                    + " items(s) and request charge of " + fluxResponse.getRequestCharge());
    
            logger.info("Item Ids " + fluxResponse
                    .getResults()
                    .stream()
                    .map(User::getId)
                    .collect(Collectors.toList()));
    
            return Flux.empty();
        }).blockLast();
    }
    

    Обратите внимание, что в этом коде мы снова используем декларативную модель Project Reactor для программирования потоков данных. Но на этот раз мы используем ее для асинхронной обработки страниц ответов на запросы. Мы демонстрируем асинхронный подход, так как в реальных вариантах использования на один запрос можно получить более сотен тысяч ответов. Агрегирование ответов на запрос может быть очень ресурсоемкой для ЦП задачей, выполнение которой упрощается благодаря повышенной эффективности работы потоков, обеспечиваемой асинхронным программированием.

    Вкратце, нам нужна высокая пропускная способность при обработке ответов на запросы или большое число страниц в секунду на поток. queryitems возвращает pagedFluxResponse экземпляра CosmosPagedFlux, а pagedFluxResponse.byPage(preferredPageSize) создает экземпляр Flux, который является источником асинхронных событий страницы. Конвейер операций в .flatMap( ... ).blockLast(); асинхронно и в псевдопараллельном режиме обрабатывает страницу ответов на запрос, связанную с каждым событием, создаваемым экземпляром Flux.

  2. Скопируйте и вставьте следующий код в метод basicOperations, перед кодом удаления документа.

    executeSimpleQuery("SELECT * FROM User WHERE User.lastName = 'Pindakova'");
    
  3. Выполните сборку и запустите CosmosApp.java в интегрированной среде разработки или запустите программу в терминале:

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

    Результат должен выглядеть следующим образом.

    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: Running SQL query...
    INFO: Got a page of query result with 1 items(s) and request charge of 2.83
    INFO: Item Ids [2]
    INFO: Deleted User 1
    

Итак, документы в приложении созданы, и мы можем запросить их из приложения. Spring Data Azure Cosmos DB предоставляет как методы производных запросов, так и методы пользовательских запросов. Оба они построены на возможностях запросов на языке SQL базового пакета SDK Azure Cosmos DB для Java версии 4. Этот урок посвящен запуску запросов Spring Data Azure Cosmos DB из своего приложения, а не с портала.

Для тестирования этих запросов будут использоваться документы WebCustomer, созданные для приложения интернет-магазина.

Создание и вызов методов производных запросов

Методы производных запросов — это методы репозитория Spring Data без реализации. Вместо этого имя метода подает сигнал Spring Data, чтобы преобразовать каждый вызов метода и его аргументы в запрос к основной базе данных. Например, при вызове findById с некоторыми аргументами Spring Data считывает имя метода как "поиск по ИД" и создает запрос базы данных, который возвращает документ, заданный аргументами.

Spring Data Azure Cosmos DB содержит ряд встроенных методов производных запросов, включая findById. В этом разделе описано, как реализовать новые методы производных запросов.

  1. Мы создадим метод производных запросов, который будет запрашивать все документы с определенным значением для поля firstName. Перейдите к файлу ReactiveWebCustomerRepository.java. Отобразится следующее объявление метода:

    Flux<WebCustomer> findByFirstName(String firstName);
    

    Этот метод репозитория объявляет Spring Data, что вам нужен метод, который при вызове запрашивает firstName. Напомним, что класс WebCustomer начался с аннотации @Container, указывающей containerName в качестве WebCustomers. Так как findByFirstName возвращает Flux<WebCustomer>, Spring Data запрашивает WebCustomers при вызове этого метода.

  2. Скопируйте и вставьте приведенный ниже код в метод runперед вызовом deleteWebCustomerDocument.

    logger.info("Running derived query...");
    Flux<WebCustomer> webCustomers = reactiveWebCustomerRepository.findByFirstName("Max");
    webCustomers.flatMap(webCustomer -> {
        logger.info("- WebCustomer is : {}", webCustomer.getUserId());
        return Mono.empty();
    }).blockLast();
    

    Обратите внимание, что в этом коде мы снова используем декларативную модель Project Reactor для программирования потоков данных. Но на этот раз мы используем ее для асинхронной обработки страниц ответов на запросы. Мы демонстрируем асинхронный подход, так как в реальных вариантах использования на один запрос можно получить более сотен тысяч ответов. Агрегирование ответов на запрос может быть очень ресурсоемкой для ЦП задачей, выполнение которой упрощается благодаря повышенной эффективности работы потоков, обеспечиваемой асинхронным программированием.

    Вкратце, нам нужна высокая пропускная способность при обработке ответов на запросы или большое число ответов в секунду на поток. findByFirstName возвращает экземпляр Flux<WebCustomer>webCustomers. Конвейер операций в .flatMap( ... ).blockLast(); работает асинхронно и в псевдопараллельном режиме в ответах на запрос, связанных с каждым событием, создаваемым Flux<WebCustomer>.

  3. Выполните сборку и запустите CosmosSample.java в интегрированной среде разработки или запустите программу в терминале:

    mvn clean package
    mvn spring-boot:run
    

    Результат должен выглядеть следующим образом.

    INFO: - WebCustomer is : maxaxam
    

Создание и вызов методов пользовательских запросов

Методы пользовательских запросов — это методы репозитория Spring Data с заметкой @Query, указывающей строку запроса, которая содержит заполнители для аргументов метода. На этот раз имя метода не влияет на выполняемый запрос. Заметка @Query подает сигнал Spring Data, чтобы создать запрос на языке SQL к основной базе данных, после введения для заполнителей значений аргументов метода.

  1. Мы создадим метод пользовательского запроса, который будет запрашивать все документы с определенным значением для поля lastName. Перейдите к файлу ReactiveWebCustomerRepository.java. Отобразится следующее объявление метода:

    @Query(value = "SELECT * FROM User WHERE User.lastName = @lastName")
    Flux<WebCustomer> findByLastName(@Param("lastName") String lastName);
    

    Этот метод репозитория объявляет Spring Data, что вам нужен метод, который при вызове запрашивает lastName. Значение аргумента lastName будет заменено на заполнитель @lastName.

  2. Скопируйте и вставьте следующий код в метод run после кода производного запроса.

    logger.info("Running custom query...");
    webCustomers = reactiveWebCustomerRepository.findByLastName("Axam");
    webCustomers.flatMap(webCustomer -> {
        logger.info("- WebCustomer is : {}", webCustomer.getUserId());
        return Mono.empty();
    }).blockLast();
    
  3. Выполните сборку и запустите CosmosSample.java в интегрированной среде разработки или запустите программу в терминале:

    mvn clean package
    mvn spring-boot:run
    

    Результат должен выглядеть следующим образом.

    INFO: Running derived query...
    INFO: - WebCustomer is : maxaxam
    INFO: Running custom query...
    INFO: - WebCustomer is : maxaxam    
    

Из этого урока вы узнали о производных и пользовательских запросах. Затем вы добавили оба типа запросов в свое приложение и извлекли записи пользователей.