练习 - 使用 Azure Cosmos DB Java SDK 进行查询

已完成

现在你已在应用程序中创建文档,接下来将从应用程序中查询这些文档。 Azure Cosmos DB Java SDK 使用 SQL 查询。 .NET SDK 对 LINQ 查询有额外的支持,但 Java SDK 没有类似的支持。 本单元着重介绍如何从应用程序(而不是从门户)运行 SQL 查询。

我们将使用你已为在线零售商应用程序创建的文档来测试这些查询。

运行 SQL 查询

  1. 下面的示例演示了如何通过 Java 代码在 SQL 中执行查询。 复制代码并将其添加到 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();
    }
    

    请注意,在此代码中,我们再次使用项目反应器的声明性数据流编程模型。 这一次,我们将使用它来异步处理查询响应页面。 我们演示了一种异步方法,因为在真实的用例中,一个查询可能会有成百上千的响应。 聚合查询响应可能是一项占用大量 CPU 的任务,它得益于异步编程的线程效率提升。

    简而言之,我们需要在处理查询响应时具有高吞吐量,或者每线程每秒页面数较高。 queryitems 会返回 CosmosPagedFlux 实例 pagedFluxResponsepagedFluxResponse.byPage(preferredPageSize) 会创建一个 Flux 实例,这是异步页面事件的源。 .flatMap( ... ).blockLast(); 内部的操作管道在与 Flux 实例发出的每个事件关联的查询响应页面上以异步方式和以伪并行方式运行。

  2. 在文件删除代码之前,复制以下代码并将其粘贴到 basicOperations 方法。

    executeSimpleQuery("SELECT * FROM User WHERE User.lastName = 'Pindakova'");
    
  3. 在 IDE 中生成并运行 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 公开派生查询方法和自定义查询方法 - 这两个方法都基于基础 Azure Cosmos DB Java SDK v4 的 SQL 语言查询功能。 本单元着重介绍如何从应用程序(而不是从门户)运行 Spring Data Azure Cosmos DB 查询。

我们将使用你已为在线零售商应用程序创建的 WebCustomer 文档来测试这些查询。

创建和调用派生查询方法

派生查询方法是无实现的 Spring Data 存储库方法;相反,方法名称向 Spring Data 发出信号,以将每个方法调用及其参数转换为对基础数据库的查询。 例如,当你使用某些参数调用 findById 时,Spring Data 会通过“按 ID 查找”读取方法名称,并汇编一个数据库查询来返回由参数指定的文档。

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. deleteWebCustomerDocument 调用之前,复制以下代码并将其粘贴到 run 方法。

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

    请注意,在此代码中,我们再次使用项目反应器的声明性数据流编程模型。 这一次,我们将使用它来异步处理查询响应页面。 我们演示了一种异步方法,因为在真实的用例中,一个查询可能会有成百上千的响应。 聚合查询响应可能是一项占用大量 CPU 的任务,它得益于异步编程的线程效率提升。

    简而言之,我们需要在处理查询响应时具有高吞吐量,或者每线程每秒响应数较高。 findByFirstName 返回 Flux<WebCustomer> 实例 webCustomers.flatMap( ... ).blockLast(); 内部的操作管道在与 Flux<WebCustomer> 发出的每个事件关联的查询响应上以异步方式和以伪并行方式运行。

  3. 在 IDE 中生成并运行 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. 在 IDE 中生成并运行 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    
    

在此单元中,你了解了派生查询和自定义查询。 然后,你将两个查询类型添加到应用程序以检索用户记录。