Azure Cosmos DB for NoSQL SDK を使用して外積クエリの結果をページ分割する

Azure Cosmos DB クエリには、通常、複数の結果ページがあります。 改ページは、Azure Cosmos DB から 1 回の実行ですべてのクエリ結果を返せない場合に、自動的にサーバー側で行われます。 多くのアプリケーションでは、SDK を使用して、パフォーマンスの高い方法でクエリ結果を一括で処理するコードを記述する必要があります。

このラボでは、結果セット全体を反復処理するためにループで使用できるフィード反復子を作成します。

開発環境を準備する

このラボで作業している環境に DP-420 のラボ コードのリポジトリをまだクローンしていない場合は、次の手順に従ってクローンします。 それ以外の場合は、以前にクローンしたフォルダーを Visual Studio Code で開きます。

  1. Visual Studio Code を起動します。

    📝 Visual Studio Code インターフェイスについてまだよく理解していない場合は、Visual Studio Code の入門ガイドを参照してください

  2. コマンド パレットを開き、Git: Clone を実行して、任意のローカル フォルダーに https://github.com/microsoftlearning/dp-420-cosmos-db-dev GitHub リポジトリをクローンします。

    💡 Ctrl + Shift + P キーボード ショートカットを使用してコマンド パレットを開くことができます。

  3. リポジトリが複製されたら、Visual Studio Code で選択したローカル フォルダーを開きます。

Azure Cosmos DB for NoSQL アカウントを作成する

Azure Cosmos DB は、複数の API をサポートするクラウドベースの NoSQL データベース サービスです。 Azure Cosmos DB アカウントを初めてプロビジョニングするときに、そのアカウントでサポートする API (たとえば、Mongo APINoSQL API) を選択します。 Azure Cosmos DB for NoSQL アカウントのプロビジョニングが完了したら、エンドポイントとキーを取得し、Azure SDK for .NET または任意の他の SDK を使用して Azure Cosmos DB for NoSQL アカウントに接続する際に使用できます。

  1. 新しい Web ブラウザー ウィンドウまたはタブで、Azure portal (portal.azure.com) に移動します。

  2. ご利用のサブスクリプションに関連付けられている Microsoft 資格情報を使用して、ポータルにサインインします。

  3. [+ リソースの作成] を選択し、Cosmos DB を検索して、新しい Azure Cosmos DB for NoSQL アカウント リソースを作成します。以下を設定して、残りの設定はすべて既定値のままにします。

    設定 Value
    サブスクリプション ’‘既存の Azure サブスクリプション’’
    リソース グループ ’‘既存のリソース グループを選択するか、新しいものを作成します’’
    アカウント名 ’‘グローバルに一意の名前を入力します’’
    場所 ’‘使用可能なリージョンを選びます’’
    容量モード プロビジョニング済みスループット
    Apply Free Tier Discount (Free レベル割引の適用) 適用しない

    📝 ご利用のラボ環境には、新しいリソース グループを作成できない制限が存在する場合があります。 その場合は、事前に作成されている既存のリソース グループを使用します。

  4. デプロイ タスクが完了するまで待ってから、このタスクを続行してください。

  5. 新しく作成された Azure Cosmos DB アカウント リソースに移動し、 [キー] ペインに移動します。

  6. このペインには、SDK からアカウントに接続するために必要な接続の詳細と資格情報が含まれています。 具体的な内容は次のとおりです。

    1. [URI] フィールドに注目します。 このエンドポイントの値は、この演習で後ほど使用します。

    2. [主キー] フィールドに注目してください。 このキーの値は、この演習で後ほど使用します。

  7. Visual Studio Code に戻ります。

Azure Cosmos DB for NoSQL アカウントにデータをシードする

cosmicworks コマンドライン ツールを使用して、Azure Cosmos DB for NoSQL アカウントにサンプル データをデプロイします。 このツールはオープンソースで、NuGet から入手できます。 このツールを Azure Cloud Shell にインストールして、データベースのシードに使用します。

  1. Visual Studio Code で、 [ターミナル] メニューを開き、 [新しいターミナル] を選択して新しいターミナル インスタンスを開きます。

  2. コンピューターでグローバルに使用するために cosmicworks コマンドライン ツールをインストールします。

     dotnet tool install cosmicworks --global --version 1.*
    

    💡 このコマンドが完了するまで数分かかる場合があります。 過去にこのツールの最新バージョンを既にインストールしている場合は、このコマンドによって警告メッセージ (*ツール ‘cosmicworks’ は既にインストールされています) が出力されます。

  3. cosmicworks を実行し、次のコマンドライン オプションを使用して Azure Cosmos DB アカウントをシードします。

    オプション Value
    –endpoint ’‘このラボで先ほどコピーしたエンドポイントの値’’
    –key ’‘このラボで先ほどコピーしたキーの値’’
    –datasets product
     cosmicworks --endpoint <cosmos-endpoint> --key <cosmos-key> --datasets product
    

    📝 たとえば、エンドポイントが https­://dp420.documents.azure.com:443/ で、キーが fDR2ci9QgkdkvERTQ== の場合、コマンドは次のようになります。cosmicworks --endpoint https://dp420.documents.azure.com:443/ --key fDR2ci9QgkdkvERTQ== --datasets product

  4. cosmicworks コマンドによって、データベース、コンテナー、および項目がアカウントに設定されるまで待ちます。

  5. 統合ターミナルを閉じます。

SDK を使用して SQL クエリの小さな結果セットで改ページする

クエリ結果を処理するときは、コードが結果のすべてのページを通過し、後続の要求を行う前にこれ以上ページが残っていないかどうかを確認する必要があります。

  1. Visual Studio Code[エクスプローラー] ペインで、10-paginate-results-sdk フォルダーを参照します。

  2. product.cs コード ファイルを開きます。

  3. Product クラスとその対応するプロパティを確認します。 具体的には、このラボでは idname、および price プロパティが使用されます。

  4. Visual Studio Code[エクスプローラー] ペインに戻り、script.cs コード ファイルを開きます。

  5. endpoint という名前の既存の変数を、先ほど作成した Azure Cosmos DB アカウントの endpoint に設定された値で更新します。

     string endpoint = "<cosmos-endpoint>";
    

    📝 たとえば、ご自分のエンドポイントが https­://dp420.documents.azure.com:443/ の場合、C# ステートメントは string endpoint = “https­://dp420.documents.azure.com:443/”; になります。

  6. key という名前の既存の変数を、先ほど作成した Azure Cosmos DB アカウントの key に設定された値で更新します。

     string key = "<cosmos-key>";
    

    📝 たとえば、キーが fDR2ci9QgkdkvERTQ== の場合、C# ステートメントは string key = “fDR2ci9QgkdkvERTQ==”; になります。

  7. string 型の sql という名前の新しい変数を SELECT p.id, p.name, p.price FROM products p の値で作成します。

     string sql = "SELECT p.id, p.name, p.price FROM products p ";
    
  8. コンストラクターへのパラメーターとして sql 変数を渡す QueryDefinition 型の新しい変数を作成します。

     QueryDefinition query = new (sql);
    
  9. 既定の空のコンストラクターを使用して、options という名前の QueryRequestOptions 型の新しい変数を作成します。

     QueryRequestOptions options = new ();
    
  10. options 変数の MaxItemCount プロパティを、50 の値に設定します。

     options.MaxItemCount = 50;
    
  11. query および options 変数をパラメーターとして渡す Container クラスのジェネリック GetItemQueryIterator メソッドを呼び出して、FeedIterator<> 型の iterator という名前の新しい変数を作成します。

     FeedIterator<Product> iterator = container.GetItemQueryIterator<Product>(query, requestOptions: options);
    
  12. iterator 変数の HasMoreResults プロパティを確認する while ループを作成します。

     while (iterator.HasMoreResults)
     {
            
     }
    
  13. while ループ内で、Product クラスを使用するジェネリック型 FeedResponseproducts という名前の変数に結果を格納する iterator 変数の ReadNextAsync メソッドを非同期的に呼び出します。

     FeedResponse<Product> products = await iterator.ReadNextAsync();
    
  14. 引き続き while ループ内で、Product 型のインスタンスを表すために変数 product を使用する products 変数を反復処理し、新しい foreach ループを作成します。

     foreach (Product product in products)
     {
    
     }
    
  15. foreach ループ内で、組み込みの Console.WriteLine 静的メソッドを使用して、product 変数の idname、および price プロパティを書式設定して出力します。

     Console.WriteLine($"[{product.id}]\t[{product.name,40}]\t[{product.price,10}]");
    
  16. while ループ内に戻り、組み込みの Console.WriteLine 静的メソッドを使用して、Press any key to get more results というメッセージを出力します。

     Console.WriteLine("Press any key to get more results");
    
  17. 引き続き while ループ内で、組み込みの Console.ReadKey 静的メソッドを使用して、次の keypress 入力をリッスンします。

     Console.ReadKey();
    
  18. 完了すると、コード ファイルが次のようになるはずです。

     using System;
     using Microsoft.Azure.Cosmos;
    
     string endpoint = "<cosmos-endpoint>";
    
     string key = "<cosmos-key>";
    
     CosmosClient client = new CosmosClient(endpoint, key);
    
     Database database = await client.CreateDatabaseIfNotExistsAsync("cosmicworks");
    
     Container container = await database.CreateContainerIfNotExistsAsync("products", "/categoryId");
    
     string sql = "SELECT p.id, p.name, p.price FROM products p ";
     QueryDefinition query = new (sql);
    
     QueryRequestOptions options = new ();
     options.MaxItemCount = 50;
    
     FeedIterator<Product> iterator = container.GetItemQueryIterator<Product>(query, requestOptions: options);
    
     while (iterator.HasMoreResults)
     {
         FeedResponse<Product> products = await iterator.ReadNextAsync();
         foreach (Product product in products)
         {
             Console.WriteLine($"[{product.id}]\t[{product.name,40}]\t[{product.price,10}]");
         }
    
         Console.WriteLine("Press any key for next page of results");
         Console.ReadKey();        
     }
    
  19. script.cs ファイルを保存します。

  20. Visual Studio Code で、10-paginate-results-sdk フォルダーのコンテキスト メニューを開き、[統合ターミナルで開く] を選択して新しいターミナル インスタンスを開きます。

  21. dotnet run コマンドを使用して、プロジェクトをビルドして実行します。

     dotnet run
    
  22. これでスクリプトによって、クエリに一致する 50 項目の最初のセットが出力されるようになります。 任意のキーを押して、一致するすべての項目に対してクエリが反復処理されるまで、50 項目の次のセットを取得します。

    💡 このクエリは、products コンテナー内の数百の項目と一致します。

  23. 統合ターミナルを閉じます。

  24. Visual Studio Code を閉じます。