演習 - 項目の読み取りとクエリ実行

完了

アプリケーションでは、Azure Cosmos DB for NoSQL コンテナーに項目を追加し、検証としてそれらの同じ項目を読み取る必要があったことを思い出してください。 この時点で、アプリケーションではコンテナーに項目を正常に追加できます。 項目を読み取る主な方法は 2 つあります。ポイント読み取りの実行とクエリの実行です。

ここでの重要な要件は次の 3 つです。

  1. 一意識別子とパーティション キー値の両方を使って項目のポイント読み取りを行う
  2. シンプルなクエリ文字列を使用してクエリを作成する
  3. フィード反復子を使用してクエリの結果を改ページする

Illustration of icons indicating data being queried using a query.

この演習を完了すると、アプリケーションの準備はほぼ完了します。 以前に作成したカテゴリと製品項目を読み取ることができるクエリが与えられます。

項目のポイント読み取り

Azure Cosmos DB の項目を取得する最も簡単な方法は、ポイント読み取りを実行することです。 ポイント読み取りでは、クエリと比較して少なく、予測可能な数の RU が使用されます。 ここでは、作成した helmets カテゴリの 1 項目のポイント読み取りを実行します。

  1. Program.cs ファイルに戻ります。

  2. gear-climb-helmets の新しい PartitionKey インスタンスを作成します。

    PartitionKey readKey = new("gear-climb-helmets");
    
  3. Container.ReadItemAsync を使い、id プロパティとパーティション キー値を使って、特定の項目のポイント読み取りを行います。

    ItemResponse<Category> readResponse = await container.ReadItemAsync<Category>(
        id: "91f79374-8611-4505-9c28-3bbbf1aa7df7",
        partitionKey: readKey
    );
    
  4. ItemResponse クラスの Resource プロパティを使って、シリアル化されたジェネリック型を取得します。

    Category readItem = readResponse.Resource;
    
  5. ポイント読み取り操作の一意識別子と要求料金を出力します。

    Console.WriteLine($"[Point read item]:\t{readItem.Id}\t(RUs: {readResponse.RequestCharge})");    
    
  6. Program.cs ファイルを保存します。

クエリを実行する

複数の項目が必要になる状況では、クエリを使用してそれらの項目を検索し、取得できます。 項目を特定のカテゴリにグループ化するために、categoryId パーティション キー プロパティを使ったことを思い出してください。 クエリにそのプロパティを含めると、1 つの論理パーティションを対象とするクエリを効果的に作成できます。 次に、クエリを使用し、tents カテゴリ内のすべての項目を検索します。

  1. Program.cs で、クエリ SELECT * FROM products p WHERE p.categoryId = 'gear-camp-tents' の新しい文字列を作成します。 ただし、categoryId フィルターに @partitionKey という名前のパラメーターを使用します。

    string statement = "SELECT * FROM products p WHERE p.categoryId = @partitionKey";
    
  2. クエリ文字列を使用し、QueryDefinition クラスの新しいインスタンスを作成します。

    var query = new QueryDefinition(
        query: statement
    );
    
  3. fluent WithParameter メソッドを使って、@partitionKey パラメーターに gear-camp-tents 値を代入します。

    var parameterizedQuery = query.WithParameter("@partitionKey", "gear-camp-tents");
    
  4. Container.GetItemQueryIterator<> を使用し、特定のクエリの反復子を取得します。

    using FeedIterator<Product> feed = container.GetItemQueryIterator<Product>(
        queryDefinition: parameterizedQuery
    );
    
  5. コンソールにクエリを書き込みます。

    Console.WriteLine($"[Start query]:\t{statement}");
    
  6. Program.cs ファイルを保存します。

クエリ結果をページ分割する

Azure Cosmos DB では、非同期的に取得できるページにクエリ結果が自動分割されます。 これらのページを管理するには、取得可能なすべての結果ページを確実に取得できるよう、特定の方法で C# コードを記述する必要があります。 ここでは、C# の while ループと foreach ループを使って、結果ページを反復処理します。

  1. Program.cs で、totalRequestCharge という名前の新しい double 変数を作成し、値を 0 に設定します。

    double totalRequestCharge = 0d;
    
  2. フィード反復子の FeedIterator.HasMoreResults プロパティが false になるまで反復処理する while ループを作成します。

    while (feed.HasMoreResults)
    {
    }
    
  3. while ループ内で、FeedIterator.ReadNextAsync メソッドを使って結果の新しいページを取得します。

    FeedResponse<Product> page = await feed.ReadNextAsync();
    
  4. 引き続き while ループ内で、FeedResponse.RequestCharge の値を使って要求料金の合計をインクリメントします。

    totalRequestCharge += page.RequestCharge;
    
  5. 引き続き while ループ内で、ページ内の実際の項目を反復処理する新しい foreach ループを作成します。

    foreach (Product item in page)
    {
    }
    
  6. foreach ループ内で、返された項目の id プロパティと name プロパティをコンソールに書き込みます。

    Console.WriteLine($"[Returned item]:\t{item.Id}\t(Name: {item.Name ?? "N/A"})");
    
  7. while ループの外部で、計算した要求料金の合計をコンソールに書き込みます。

    Console.WriteLine($"[Query metrics]:\t(RUs: {totalRequestCharge})");
    

    ヒント

    どのコードを while ループと foreach ループの内部または外部に配置するかわからない場合は、「作業を確認する」の「コードのレビュー」セクションに移動してください。

  8. Program.cs ファイルを保存します。

作業を確認

これで、アプリではコンテナーから項目を読み取り、クエリを実行できるようになりました。 ここでは、両方の操作の結果を確認できるようにアプリケーションを実行します。

  1. ターミナルで .NET アプリケーションを実行します。

    dotnet run
    
  2. アプリケーションを実行した出力を確認します。 出力は、次の例と一致しているはずです。

    ...
    [Point read item]:      91f79374-8611-4505-9c28-3bbbf1aa7df7    (RUs: 1)
    [Start query]:          SELECT * FROM products p WHERE p.categoryId = @partitionKey
    [Returned item]:        5df21ec5-813c-423e-9ee9-1a2aaead0be4    (Name: N/A)
    [Returned item]:        e8dddee4-9f43-4d15-9b08-0d7f36adcac8    (Name: Cirroa Tent)
    [Returned item]:        e6f87b8d-8cd7-4ade-a005-14d3e2fbd1aa    (Name: Kuloar Tent)
    [Returned item]:        f7653468-c4b8-47c9-97ff-451ee55f4fd5    (Name: Mammatin Tent)
    [Returned item]:        6e3b7275-57d4-4418-914d-14d1baca0979    (Name: Nimbolo Tent)
    [Query metrics]:        (RUs: 2.94)
    

    ヒント

    この出力例で示されている RU は、実際の出力と異なる場合があります。

    category 項目が、products に使用する型に正常に逆シリアル化されていることに気付きましたか? category 項目には name プロパティがなかったため、そのプロパティはその既定値のままでした。 型チェック、スキーマ管理、シリアル化および逆シリアル化は、すべてアプリケーションで、完全にクライアント側で管理できます。