演習 - 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();
    }
    

    このコードでは、Project Reactor の宣言型データ フロー プログラミング モデルを再び使用していることに注意してください。 今回は、これを使用してクエリ応答ページを非同期で処理します。 実際のユースケースでは、クエリに対して数百または数千の応答が発生する可能性があるため、非同期の方法を示します。 クエリ応答の集計は、CPU を集中的に使用するタスクになる可能性があり、非同期プログラミングのスレッド効率向上の恩恵を受けます。

    つまり、クエリ応答の処理スループットを高く (スレッドあたりのページ数/秒を多く) する必要があります。 queryitems からは CosmosPagedFlux のインスタンス pagedFluxResponse が返され、pagedFluxResponse.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);
    

    このリポジトリ メソッドを使用して、呼び出し時に firstName のクエリを実行するメソッドが必要であることを Spring Data に宣言します。 WebCustomer クラスは containerNameWebCustomers として指定する @Container 注釈で始まったことを思い出してください。 findByFirstName からは Flux<WebCustomer> が返されるため、このメソッドの呼び出し時に WebCustomers のクエリを実行することは Spring Data によって認識されています。

  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();
    

    このコードでは、Project Reactor の宣言型データ フロー プログラミング モデルを再び使用していることに注意してください。 今回は、これを使用してクエリ応答ページを非同期で処理します。 実際のユースケースでは、クエリに対して数百または数千の応答が発生する可能性があるため、非同期の方法を示します。 クエリ応答の集計は、CPU を集中的に使用するタスクになる可能性があり、非同期プログラミングのスレッド効率向上の恩恵を受けます。

    つまり、クエリ応答の処理スループットを高く (スレッドあたりの応答数/秒を多く) する必要があります。 findByFirstName から Flux<WebCustomer> インスタンス webCustomers が返されます。 .flatMap( ... ).blockLast(); 内の操作のパイプラインは、Flux<WebCustomer> によって生成される各イベントに関連付けられているクエリ応答で、非同期的に擬似並列で動作します。

  3. IDE で CosmosSample.java をビルドして実行するか、ターミナルで次のコマンドを使用してプログラムを実行します。

    mvn clean package
    mvn spring-boot:run
    

    ターミナルでの出力は次のようになります。

    INFO: - WebCustomer is : maxaxam
    

カスタム クエリ メソッドを作成して呼び出す

"カスタム クエリ メソッド" は、クエリ文字列を指定する @Query 注釈を持つ Spring Data リポジトリ メソッドです。また、クエリ文字列にはメソッド引数のプレースホルダーが含まれています。 今回、メソッド名は、実行されるクエリに影響がありません。 引数のプレースホルダーにメソッド引数の値を入力した "" に、@Query 注釈を使用して、基となるデータベースに SQL 言語クエリを発行するように Spring Data に通知します。

  1. lastName フィールドに特定の値を持つすべてのドキュメントのクエリを実行するカスタム クエリ メソッドを作成します。 ReactiveWebCustomerRepository.java に移動します。 次のメソッド宣言が表示されます。

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

    このリポジトリ メソッドを使用して、呼び出し時に lastName のクエリを実行するメソッドが必要であることを Spring Data に宣言します。 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    
    

このユニットでは、派生クエリとカスタム クエリについて学習しました。 次に、ユーザー レコードを取得する両方のクエリをアプリケーションに追加しました。