演習 - NoSQL データをプログラムで作成、読み取り、更新、および削除する

完了

Azure Cosmos DB に接続しました。 このユニットでは、WebCustomers コレクションでユーザー ドキュメントを作成します。 次に、ID でドキュメントを取得し、置換し、削除します。

プログラムによるドキュメントの操作

データは、Azure Cosmos DB 内の JSON ドキュメントに格納されます。 ドキュメントは、ポータルまたはプログラムを使用して、作成、取得、置換、または削除できます。 このラボでは、プログラムによる操作に注目します。 Azure Cosmos DB では .NET、.NET Core、Java、Node.js、Python 用のクライアント側 SDK が提供されており、いずれもこれらの操作をサポートします。 このモジュールでは、Java SDK を使用して、Azure Cosmos DB に格納されている NoSQL データに対して CRUD (作成、取得、更新、削除) 操作を実行します。

Azure Cosmos DB ドキュメントに対する主要な操作は、CosmosAsyncContainer クラスの一部です。

アップサートでは、ドキュメントが既に存在するかどうかに応じて、作成または置換操作が実行されます。

これらの操作のいずれかを実行するには、データベースに格納されているオブジェクトを表すヘルパー クラス (Java POJO クラス) が必要です。 ユーザーのデータベースを操作しているため、ユーザー エンティティを表す User クラスが必要になります。 このクラスには、名、姓、ユーザー ID などのプライマリ データが格納されます (ID は、水平スケーリングを可能にするパーティション キーであるため、必須です)。

各ユーザーには配送設定とクーポンが関連付けられているため、ShippingPreferenceCouponsUsed のデータ型を使ってこれらのエンティティを表す必要があります。 最後に、各ユーザーには、バインドされていない可能性のあるいくつかの注文履歴も存在することがあるため、対応する Java POJO クラスに別の OrderHistory エンティティも必要です。

src/main/java/com/azure/azure-cosmos-java-sql-app-mslearn に移動し、datatypes フォルダーを確認します。 UserShippingPreferenceOrderHistory、および CouponsUsed といういくつかの POJO があります。 これで、すべてのエンティティ POJO とそのヘルパー クラスが用意されました。

次に、いくつかのエンティティを作成し、Azure Cosmos DB コンテナーとそれに含まれるドキュメントに対して、いくつかの基本的な CRUD 操作を実行します。 JSON ドキュメントを直接指定する Jackson ObjectNode インスタンスを Azure Cosmos DB に渡すことができます。 ただし、Azure Cosmos DB には Java POJO を JSON にシリアル化することもできます。このアプローチは、最も簡単な方法としてお勧めします (他のすべての点は同じです)。

ドキュメントの作成

  1. User.java を開き、内容を確認します。 次のように表示されます。

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

    iduserId などのフィールドに対するアクセス メソッドは "暗黙的である" (コードで定義されていない) ことに注意してください。 この動作が可能なのは、Project Lombok @Data 注釈を使用してそれらを自動的に作成しているためです。

    @NoArgsConstructor 注釈によって、既定のフィールド値を設定する引数なしでコンストラクターが生成されます。 @AllArgsConstructor 注釈によって、すべてのフィールド値を直接指定する引数の一式が設定された別のコンストラクターが生成されます。

    User には id プロパティがあることに注意してください。 すべての Azure Cosmos DB ドキュメントには id プロパティが必要であるため、JSON ドキュメントにシリアル化する予定のすべての POJO には id フィールドが必要です。

  2. 次のメソッドを 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. 次に、basicOperations メソッドに戻り、そのメソッドの末尾にある 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. IDE で CosmosApp.java をビルドして実行するか、またはターミナルで次を使用してプログラムを実行します。

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

    アプリケーションで新しいユーザー ドキュメントが作成されるたびに、ターミナルに出力が表示されます。

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

    タイムスタンプなど、ロガーによって生成されたその他のテキストが表示される場合があります。

おめでとうございます。 Java アプリケーションから Azure Cosmos DB に最初のデータを作成できました。 いったん手を止め、ここで行ったことを評価してみましょう。

basicOperations には、次の 3 つの新しいアクションがあります。

  1. maxaxamUser インスタンスを作成します。
  2. nelapinUser インスタンスを作成します。
  3. createUserDocumentsIfNotExist を呼び出し、一覧で maxaxamnelapin を渡します。

createUserDocumentsIfNotExist を呼び出すと、両方の User インスタンスが Azure Cosmos DB に項目およびドキュメントとして挿入されます。 User インスタンスをリストとして渡しているのは、最小限のコンピューティング リソースを使用して、Azure Cosmos DB に POJO をすばやく取り込むための高パフォーマンスのメソッドをモデル化するためです。 createUserDocumentsIfNotExist では、POJO のリストの効率的な非同期挿入が実装されています。

スレッドあたりの要求数/秒を最大にすることが目標である場合を考えてください。 比較のために、(readItem チェックを一時的に無視して) createUserDocumentsIfNotExist を書き込む同期アプローチでは、users の各 User インスタンスに対して反復処理を行います。 Useru ごとに、createItem に対して "ブロックする" 呼び出しを行います。

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

この同期スタイルでは、"要求を発行し"、"応答を待機し"、"次の要求を発行する" という、直感的なプロセスが実装されます。 ただし、createUserDocumentsIfNotExist ではこの方法は使用されていません。ブロッキング呼び出しを使用すると、基本的に、要求応答時間の間に CPU サイクルが無駄に消費され、要求数/秒が少なくなるためです。

複数のスレッドを生成して並列ブロッキング要求呼び出しを行うことで、この要求数/秒の問題を回避できます。 複数のスレッドによって、実行時間は改善されます。 ただし、目標がスレッド リソースを節約することである場合、これはまだ無駄です。 代わりに他の何かに対するマルチタスクである場合、要求応答時間中に各スレッドはループし、スレッドあたりの要求数/秒が少なくなります。

このような理由から、そして Java POJO のスレッド効率の高い挿入を示すため、代わりにドキュメントの挿入を非同期に行う例を提供してあります。 Azure Cosmos DB Java SDK v4 の非同期サポートの基になっている Project Reactor は、非同期イベントドリブン プログラミングのための、ストリームベースの "宣言型データフロー" プログラミング モデルを提供する、Java アプリケーション フレームワークです。 createDocumentsIfNotExist では、Project Reactor の非同期プログラミングが実装されています。

createUserDocumentsIfNotExist では、Flux.fromIterable(users) は Project Reactor ファクトリ メソッドです。 非同期イベントのソースである Flux インスタンスが作成されます。 この場合、各非同期 "イベント" には User インスタンス引数が含まれます。 Flux インスタンスには、maxaxam 用と nelapin 用の 2 つのイベントが含まれています。 .flatMap( ... ).blockLast(); 内のコードでは、Flux インスタンスによって生成されたイベントに対して実行されるシーケンシャル操作の "パイプライン" を定義します。

このような操作の 1 つが createItem です。 このパイプラインは、createItem 呼び出しをブロックしないことを除き、同期の実装とほぼ同じであるという考え方です。 具体的には、blockLast() の呼び出しによってアセンブルされたパイプラインに "サブスクライブ" され、Flux から "非同期" に 2 つのイベントが生成されます。 次に、.flatMap( ... ).blockLast(); 内のパイプラインによって、これらの各イベントは疑似並列形式で処理します。 1 つの要求が発行されて、応答が待機されている間、Project Reactor ではバックグラウンドで他の要求が処理されます。"これは、スレッドごとの要求数/秒の最大化において重要な要素です"。

Project Reactor を使用した効率的な非同期データベース要求を示したので、このラボの残りの部分では、わかりやすくするため、ブロッキング (同期) 呼び出しを使用します。 Project Reactor の詳細については、Azure Cosmos DB の「Reactor パターン ガイド」を参照してください。

ドキュメントを読み取る

  1. データベースからドキュメントを読み取るには、次のメソッドを 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. 次のコードをコピーし、basicOperations メソッドの最後にあるドキュメント作成コードの後に貼り付けます。

    readUserDocument(maxaxam);
    
  3. IDE で CosmosApp.java をビルドして実行するか、またはターミナルで次を使用してプログラムを実行します。

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

    ターミナルに次の出力が表示されます。"Read user 1" は、ドキュメントが取得されたことを示します。

    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
    

    ロガーによって生成される追加のテキストも表示される場合があります。

ドキュメントを置換する

Azure Cosmos DB では、JSON ドキュメントの置換がサポートされています。 ここでは、姓の変更を反映するようにユーザー レコードを更新します。

  1. CosmosApp.java ファイルの readUserDocument メソッドの後に replaceUserDocument メソッドを追加します。

    /**
     * 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. 次のコードをコピーし、basicOperations メソッドの最後にあるドキュメント読み取りコードの後に貼り付けます。

    maxaxam.setLastName("Suh");
    replaceUserDocument(maxaxam);
    
  3. IDE で CosmosApp.java をビルドして実行するか、またはターミナルで次を使用してプログラムを実行します。

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

    ターミナルに次の出力が表示されます。"Replaced last name for Suh" は、ドキュメントが置き換えられたことを示します。

    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
    

ドキュメントの削除

  1. deleteUserDocument メソッドをコピーして 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. 次のコードをコピーして、basicOperations メソッドの末尾に貼り付けます。

    deleteUserDocument(maxaxam);
    
  3. IDE で CosmosApp.java をビルドして実行するか、またはターミナルで次を使用してプログラムを実行します。

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

    ターミナルに次の出力が表示されます。"Deleted user 1" は、ドキュメントが削除されたことを示します。

    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
    

プログラムによるドキュメントの操作

データは、Azure Cosmos DB 内の JSON ドキュメントに格納されます。 ドキュメントは、ポータルまたはプログラムを使用して、作成、取得、置換、または削除できます。 このラボでは、プログラムによる操作に注目します。 これらの操作はすべて、Azure Cosmos DB Java SDK で使用できます。また、Spring Data プログラミング モデルからもアクセスできます。 このモジュールでは、Spring Data Azure Cosmos DB を使用して、Azure Cosmos DB に格納されている NoSQL データに対して CRUD (作成、取得、更新、削除) 操作を実行します。

Spring Data Azure Cosmos DB ドキュメントの主な操作は、Spring Data プログラミング モデルの基本的な操作です。

  • save - ドキュメントが既に存在するかどうかに応じて、ドキュメントのポイント書き込みまたは更新を行います。
  • view - ドキュメントのポイント読み込みを行います
  • delete - ドキュメントのポイント削除を行います

これらの操作のいずれかを実行するには、データベースに格納されているオブジェクトを表すヘルパー クラス (Java POJO クラス) が必要です。 オンライン顧客のデータベースを使用しているので、WebCustomer クラスを使用してユーザー エンティティを表すことをお勧めします。 このクラスには、名、姓、ユーザー ID などのプライマリ データが格納されます (ID は、水平スケーリングを可能にするパーティション キーであるため、必須です)。

各 Web 顧客には配送設定とクーポンが関連付けられているため、ShippingPreferenceCouponsUsed のデータ型を使ってこれらのエンティティを表す必要があります。 最後に、各 Web 顧客には、バインドされていない可能性のあるいくつかの注文履歴も存在することがあるため、対応する Java POJO クラスに別の OrderHistory エンティティも必要です。

src/main/java/com/azure/cosmos/examples/springexamples に移動します。 WebCustomer POJO があります。 次に common フォルダー内を見ます。 ShippingPreferenceOrderHistoryCouponsUsed といういくつかの POJO があります。 これで、すべてのエンティティ POJO とそのヘルパー クラスが用意されました。

次に、いくつかのエンティティを作成し、Azure Cosmos DB コンテナーとそれに含まれるドキュメントに対して、いくつかの基本的な CRUD 操作を実行します。 JSON ドキュメントを直接指定する Jackson ObjectNode インスタンスを Azure Cosmos DB に渡すことができます。 ただし、Azure Cosmos DB には Java POJO を JSON にシリアル化することもできます。このアプローチは、最も簡単な方法としてお勧めします (他のすべての点は同じです)。

ドキュメントの作成と更新

  1. WebCustomer.java を開き、その内容を確認します。 次のように表示されます。

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

    iduserId などのフィールドに対するアクセス メソッドは "暗黙的である" (コードで定義されていない) ことに注意してください。 この動作が可能なのは、Project Lombok @Data 注釈を使用してそれらを自動的に作成しているためです。

    @NoArgsConstructor 注釈によって、既定のフィールド値を設定する引数なしでコンストラクターが生成されます。 @AllArgsConstructor 注釈によって、すべてのフィールド値を直接指定する引数の一式が設定された別のコンストラクターが生成されます。

    WebCustomer には id プロパティがあることに注意してください。 すべての Azure Cosmos DB ドキュメントには id プロパティが必要であるため、JSON ドキュメントにシリアル化する予定のすべての POJO には id フィールドが必要です。

  2. 次のメソッドを 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. run メソッドを見つけて、そのメソッドの最後に次のコードを追加します。

    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. IDE で CosmosSample.java をビルドして実行するか、ターミナルで次のコマンドを使用してプログラムを実行します。

    mvn clean package
    mvn spring-boot:run
    

    ターミナルの出力に次のような内容が表示されます

    INFO: Creating WebCustomer 1
    INFO: Creating WebCustomer 2
    

おめでとうございます。 Java アプリケーションから Azure Cosmos DB に最初のデータを作成し、更新しました。 いったん手を止め、ここで行ったことを評価してみましょう。

run には、次の 3 つの新しいアクションがあります。

  1. maxaxamWebCustomer インスタンスを作成または更新します。
  2. nelapinWebCustomer インスタンスを作成または更新します。
  3. createWebCustomerDocumentsIfNotExist を呼び出し、一覧で maxaxamnelapin を渡します。

createWebCustomerDocumentsIfNotExist を呼び出すと、両方の WebCustomer インスタンスが Azure Cosmos DB に項目およびドキュメントとして挿入されます。 WebCustomer インスタンスをリストとして渡しているのは、最小限のコンピューティング リソースを使用して、Azure Cosmos DB に POJO をすばやく取り込むための高パフォーマンスのメソッドをモデル化するためです。 createWebCustomerDocumentsIfNotExist では、POJO のリストの効率的な非同期挿入が実装されています。 いずれかのドキュメントが既に存在する場合、save によってドキュメントの作成ではなく更新が実行されます。

スレッドあたりの要求数/秒を最大にすることが目標である場合を考えてください。 比較として、createWebCustomerDocumentsIfNotExist を書き込む同期アプローチは、webCustomers の各 WebCustomer インスタンスを反復処理することです。 WebCustomerwebCustomer ごとに、save に対して "ブロックする" 呼び出しを行います。

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

この同期スタイルでは、"要求を発行し"、"応答を待機し"、"次の要求を発行する" という、直感的なプロセスが実装されます。 ただし、createWebCustomerDocumentsIfNotExist ではこの方法は使用されていません。ブロッキング呼び出しを使用すると、基本的に、要求応答時間の間に CPU サイクルが無駄に消費され、要求数/秒が少なくなるためです。

複数のスレッドを生成して並列ブロッキング要求呼び出しを行うことで、この要求数/秒の問題を回避できます。 複数のスレッドによって、実行時間は改善されます。 ただし、目標がスレッド リソースを節約することである場合、これはまだ無駄です。 代わりに他の何かに対するマルチタスクである場合、要求応答時間中に各スレッドはループし、スレッドあたりの要求数/秒が少なくなります。

このような理由から、そして Java POJO のスレッド効率の高い挿入を示すため、代わりにドキュメントの挿入を非同期に行う例を提供してあります。 Spring Data の非同期サポートの基になっている Project Reactor は、非同期イベントドリブン プログラミングのための、ストリームベースの "宣言型データフロー" プログラミング モデルを提供する、Java アプリケーション フレームワークです。 createWebCustomerDocumentsIfNotExist では、Project Reactor の非同期プログラミングが実装されています。

createWebCustomerDocumentsIfNotExist では、Flux.fromIterable(webCustomers) は Project Reactor ファクトリ メソッドです。 非同期イベントのソースである Flux インスタンスが作成されます。 この場合、各非同期 "イベント" には WebCustomer インスタンス引数が含まれます。 Flux インスタンスには、maxaxam 用と nelapin 用の 2 つのイベントが含まれています。 .flatMap( ... ).blockLast(); 内のコードでは、Flux インスタンスによって生成されたイベントに対して実行されるシーケンシャル操作の "パイプライン" を定義します。

この場合、パイプラインの 2 つの操作は save の呼び出しです。 このパイプラインは、save 呼び出しをブロックしないことを除き、同期の実装とほぼ同じであるという考え方です。 具体的には、blockLast() の呼び出しによってアセンブルされたパイプラインに "サブスクライブ" され、Flux から "非同期" に 2 つのイベントが生成されます。 次に、.flatMap( ... ).blockLast(); 内のパイプラインによって、これらの各イベントは疑似並列形式で処理します。 1 つの要求が発行されて、応答が待機されている間、Project Reactor ではバックグラウンドで他の要求が処理されます。"これは、スレッドごとの要求数/秒の最大化において重要な要素です"。

Project Reactor を使用した効率的な非同期データベース要求を示したので、このラボの残りの部分では、わかりやすくするため、非同期呼び出しのブロック (実質的に同期呼び出し) を使用します。 Project Reactor の詳細については、Azure Cosmos DB の「Reactor パターン ガイド」を参照してください。

ドキュメントを読み取る

  1. データベースからドキュメントを読み取るには、次のメソッドを 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. 次のコードをコピーし、run メソッドの最後にあるドキュメント作成コードの後に貼り付けます。

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

    mvn clean package
    mvn spring-boot:run
    

    ターミナルの出力に次のような内容が表示されます。 "Read user 1" は、ドキュメントが取得されたことを示します。

    INFO: Read webCustomer 1
    

ドキュメントの削除

  1. deleteWebCustomerDocument メソッドをコピーして 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. 次のコードをコピーして、run メソッドの末尾に貼り付けます。

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

    mvn clean package
    mvn spring-boot:run
    

    ターミナルの出力に次のような内容が表示されます。 "Deleted user 1" は、ドキュメントが削除されたことを示します。

    INFO: Deleted webCustomer 1
    

このユニットでは、Azure Cosmos DB データベース内のドキュメントの作成、更新、読み取り、削除を行いました。