演習 - 出力バインディングを使用してデータを書き込む

完了

前の演習で、Azure Cosmos DB データベース内のブックマークを検索するシナリオを実装しました。 このブックマークのコレクションからデータを読み取るように入力バインディングを構成しました。 しかし、できることはもっとたくさんあります。 シナリオを拡張して書き込みも行ってみましょう。 次のフローチャートについて考えてみます。

Decision flow diagram illustrating the process of adding a bookmark in Azure Cosmos DB back-end and returning a response.

このシナリオでは、コレクションにブックマークを追加する要求を受信します。 この要求によって目的のキーまたは ID が、ブックマーク URL と共に渡されます。 フローチャート内で確認できるように、そのキーがバックエンド内に既に存在する場合はエラーで応答します。

渡されたキーが見つからない場合は、新しいブックマークをデータベースに追加します。 それで終わりにしてもかまいませんが、もう少しやってみましょう。

フローチャート内の別の手順に気付きましたか。 これまで、処理の観点から受信したデータに対して大したことは行っていません。 受信した内容をデータベースに移動します。 ただし、実際のソリューションでは、そのデータを何らかの方法で処理するでしょう。 同じ関数ですべての処理を実行することもできますが、この演習では、追加の処理を別のコンポーネントまたはビジネス ロジックの一部にオフロードするパターンを紹介します。

このブックマーク シナリオでの作業のオフロードを示す良い例として、どのようなものが考えられるでしょうか? 新しいブックマークを QR コード生成サービスに送信するというのはどうでしょう。 そのサービスによって URL の QR コードが生成され、画像が Blob Storage に格納され、QR 画像のアドレスがブックマーク コレクション内のエントリに追加されます。 QR イメージを生成するサービスの呼び出しには時間がかかります。 そのため、結果を待たずに関数にタスクを渡して、このタスクを非同期で完了させます。

Azure Functions では、さまざまな統合ソースに対して入力バインディングがサポートされているのと同様に、出力バインディング用のテンプレートのセットも用意されています。そのため、データ ソースへのデータの書き込みを容易に行うことができます。 出力バインディングは、function.json ファイルでも構成されています。 この演習で示すように、複数のデータ ソースとサービスを操作するように関数を構成できます。

重要

この演習では、サンドボックスのリソースとこれまでのユニットで作成したとリソース (具体的には、Azure Cosmos DB データベース、ブックマーク、入力バインディング) を基にします。 これまでのユニットの演習を完了していない場合、この演習を完了することはできません。

HTTP によってトリガーされる関数を作成する

  1. Azure portal で、HttpTrigger2 関数ページの上部にある階層リンク パスで関数アプリの名前を選択して、作成した関数アプリにアクセスします。

  2. [概要] ページの [関数] タブには、作成した HTTP トリガー関数が表示されているはずです。

  3. [関数] タブの [作成] を選択します。[関数の作成] ペインが表示されます。

  4. [テンプレートの選択] セクションで [HTTP トリガー] を選択し、[作成] を選択します。 HttpTrigger3 関数の [概要] ペインが表示されます。

Azure Cosmos DB 入力バインディングを追加する

Azure Cosmos DB 入力バインディングをもう 1 つ追加しましょう。

  1. HttpTrigger3 関数メニューで、[統合] を選択します。 [統合] ウィンドウが表示されます。

  2. [入力] ボックスで、[入力の追加] を選択します。 [入力の作成] ペインが表示されます。

  3. [バインドの種類] ドロップダウン リストで、[Azure Cosmos DB] を選択します。

  4. [Cosmos DB アカウント接続] 設定には、前の演習で作成した接続が事前入力されています。

    接続が一覧表示されない場合は、次の手順に従って新しい接続を作成します。

    1. [Azure Cosmos DB の詳細] セクションの [Cosmos DB アカウント接続] 設定で、[新規] リンクを選択します。

    2. [新しい Cosmos DB 接続] ダイアログ ボックスが表示されたら、[OK] を選択して接続を作成します。 新しい Cosmos DB アカウント接続が作成されます。

  5. このペインのその他の設定に、次の値を入力します。 設定の目的の詳細を確認するには、右側にある情報アイコンをいつでも選択できます。

    設定 説明
    ドキュメント パラメーター名 bookmark コードでこのバインディングを識別するための名前。
    データベース名 func-io-learn-db 使用するデータベース。 この値は、このレッスンで以前に設定したデータベース名です。
    コレクション名 Bookmarks データの読み取り元のコレクションの名前。 この設定はレッスンの前半で定義しました。
    ドキュメント ID {id} {id} を追加して、正しいバインド式を使用し、クエリ文字列で渡されるパラメーターを受け入れます。
    パーティション キー {id} ここでも、{id} を追加して正しいバインド式を使用し、クエリ文字列で渡されるパラメーターを受け入れます。
    SQL クエリ (任意) 空白のまま ID に基づき、一度に 1 項目だけ取得しています。 そのため、この場合は SQL クエリを使用するより、[ドキュメント] 設定を使用してフィルター処理する方が効果的です。 エントリを 1 つ返す SQL クエリを作成することもできます (SELECT * from b where b.ID = /id)。 このクエリでは確かに項目が返されますが、項目コレクション内に返されます。 コードで無駄にコレクションを操作しなければならないことがあります。 複数のドキュメントを取得するときに SQL クエリの手法を使用してください。

    前の演習で作成した入力バインドと同様に、特定の ID を持つブックマークを調べる必要があるため、関数によってクエリ文字列で受け取るドキュメント ID を、"バインド式" と呼ばれるバインドに関連付けました。 関数のトリガーは、クエリ文字列を使用して検索する ID を指定した HTTP 要求です。 バインディングは、0 (見つからない) または 1 (見つかった) ドキュメントを返します。

  6. [OK] を選択して、入力バインディング構成を保存します。

これで Azure Cosmos DB 入力バインディングが用意されました。 新しいエントリをコレクションに書き込むことができるように、出力バインディングを追加しましょう。

Azure Cosmos DB の出力バインディングの追加

  1. HttpTrigger3[統合] ペインの [出力] ボックスで、[出力の追加] を選択します。 [出力の作成] ペインが表示されます。

  2. [バインドの種類] の下のドロップダウン リストから、[Azure Cosmos DB] を選択します。

  3. [Cosmos DB アカウント接続] 設定には、先ほど作成した接続が事前入力されているはずです。 入力されていない場合は、ドロップダウン リストを展開し、HttpTrigger3 入力バインディングに定義した接続を選択します。

  4. 出力バインディングの残りの設定に、次の値を入力します。

    設定 説明
    ドキュメント パラメーター名 newbookmark コードでこのバインディングを識別するための名前。 このパラメーターは新しいブックマーク エントリを書き込むために使用されます。
    データベース名 func-io-learn-db 使用するデータベース。 この値は、このレッスンで以前に設定したデータベース名です。
    コレクション名 Bookmarks データの読み取り元のコレクションの名前。 この値は、レッスンの前半で定義したコンテナー名です。
    パーティション キー /id 前の手順で Bookmarks Azure Cosmos DB コンテナーを作成したときに定義したパーティション キーを追加します。 ここに入力するキー (入力バインディング構成 <key> で指定) は、コンテナー内のキーと一致する必要があります。
  5. [OK] を選択して、この出力バインディング構成を保存します。

これで、コレクションから読み込むためのバインディングとコレクションに書き込むためのバインディングを用意できました。

Azure Queue Storage 出力バインディングを追加する

Azure Queue Storage は、世界中のどこからでもアクセスできるメッセージを格納するためのサービスです。 単一のメッセージのサイズは 64 KB ほどになります。キューには、ストレージ アカウントで定義されている合計容量に達するまで、数百万のメッセージを格納できます。 次の図は、このシナリオでのキューの使用方法の概要を示します。

Illustration showing a storage queue with a function pushing and another function popping messages.

この例では、add-bookmark という名前の関数がキューにメッセージを追加し、別の gen-qr-code という名前の関数が同じキューからメッセージをポップし、要求を処理していることがわかります。 add-bookmark からキューにメッセージを書き込む ("プッシュする") ので、新しい出力バインドをソリューションに追加します。

ポータルから、バインドを作成しましょう。

  1. 関数の [統合] ペインの [出力] ボックスで、[出力の追加] を選択します。 [出力の作成] ペインが表示されます。

  2. [バインドの種類] ドロップダウン リストで、[Azure Queue Storage] を選択します。

    Microsoft.Azure.WebJobs.Extensions.Storage 拡張機能をインストールするように求めるメッセージが表示されたら、[インストール] を選択し、インストールが完了するまで待ちます。

次に、キューをホストするストレージ アカウント接続を設定します。

  1. [ストレージ アカウント接続] で、[新規] を選択します。 [新しいストレージ アカウント接続] ダイアログ ボックスが表示されます。

  2. このモジュールの最初に、関数アプリを作成したときに、ストレージ アカウントも作成されました。 それをドロップダウン リストから選択し、[OK] を選択します。

    [ストレージ アカウント接続] 設定には、接続の名前が設定されます。

既定値のままにしておくこともできますが、残りのプロパティにより意味を持たせるために設定をいくつか変更しましょう。

  1. [出力の作成] ペインで、次の古い値を新しい値に置き換えて設定を完成させます。

    設定 古い値 新しい値 説明
    メッセージ パラメーター名 outputQueueItem newmessage コードで使用するバインディング プロパティ。
    キュー名 outqueue bookmarks-post-process 別の関数が追加の処理を行えるようにブックマークを配置するキューの名前です。
  2. [OK] を選択して、Azure Queue Storage の出力構成を保存します。

関数の実装を更新する

これで、すべてのバインドがセットアップされました。 それらをこの関数で使ってみましょう。

  1. コード エディターで index.js ファイルを開くには、関数 HttpTrigger3 を選択します。

  2. メニューで、[開発者] の下にある [コードとテスト] を選択します。 関数の [コード + テスト] ペインが表示されます。

  3. index.js ファイル内のすべてのコードを次のスニペットのコードに置き換えてから、メニュー バーで [保存] を選択します。

    module.exports = function (context, req) {
    
        var bookmark = context.bindings.bookmark;
        if(bookmark){
                context.res = {
                status: 422,
                body : "Bookmark already exists.",
                headers: {
                'Content-Type': 'application/json'
                }
            };
        }
        else {
            
            // Create a JSON string of our bookmark.
            var bookmarkString = JSON.stringify({ 
                id: req.body.id,
                url: req.body.url
            });
    
            // Write this bookmark to our database.
            context.bindings.newbookmark = bookmarkString;
    
            // Push this bookmark onto our queue for further processing.
            context.bindings.newmessage = bookmarkString;
    
            // Tell the user all is well.
            context.res = {
                status: 200,
                body : "bookmark added!",
                headers: {
                'Content-Type': 'application/json'
                }
            };
        }
        context.done();
    };
    

このコードで何が行われるのかを詳しく見てみましょう。

  • この関数によってデータが変更されるので、HTTP 要求が POST になり、ブックマーク データが要求本文の一部になると想定しています。
  • Azure Cosmos DB の入力バインディングでは、受信する id を使用してドキュメントまたはブックマークの取得が試みられます。 エントリが見つかると、bookmark オブジェクトが設定されます。 if(bookmark) 条件では、エントリが見つかったかどうかが確認されます。
  • データベースへの追加は、JSON 文字列として作成した新しいブックマーク エントリに context.bindings.newbookmark バインディング パラメーターを設定するのと同じくらいシンプルです。
  • キューへのメッセージの投稿は、context.bindings.newmessage パラメーターを設定するのと同じくらいシンプルです。

Note

行ったタスクは、キュー バインディングの作成のみです。 キューの作成は明示的に行っていません。 バインディングの機能を確認しましょう。 次の通知で宣言されているように、キューが存在しない場合、自動的に作成されます。

Screenshot showing message that the queue will be auto-created.

これで終了です。 次のセクションで作業内容の動作を確認してみましょう。

  1. コード エディターで run.ps1 ファイルを開くには、ペインの上部にある階層リンクから HttpTrigger3 関数を選択します。

  2. [関数] メニューで、[開発者] の下にある [コードとテスト] を選択します。 HttpTrigger3 関数の[コードとテスト] ペインが表示され、run.ps1 の既定の内容が表示されます。

  3. このファイルの内容を次のコードに置き換えます。

    using namespace System.Net
    
    param($Request, $bookmark, $TriggerMetadata)
    
    if ($bookmark) {
        $status = 422
        $body = "Bookmark already exists."
    }
    else {
        $newBookmark = @{ id = $Request.Body.id; url = $Request.Body.url }
    
        Push-OutputBinding -Name newbookmark -Value $newBookmark
    
        Push-OutputBinding -Name newmessage -Value $newBookmark
    
        $status = [HttpStatusCode]::OK
        $body = "bookmark added!"
    }
    
    Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
        StatusCode = $status
        Body = $body
        ContentType = "application/json"
    })
    
  4. コマンド バーの [保存] を選択します。 接続が確立され、ログ ファイル セッションが開かれます。

このコードで何が行われるのかを詳しく見てみましょう。

  • この関数によってデータが変更されるので、HTTP 要求が POST になり、ブックマーク データが要求本文の一部になると想定しています。
  • Azure Cosmos DB の入力バインディングで、要求内の id を使用して、ドキュメント (ブックマーク) を取得しようとします。 エントリが見つかると、bookmark オブジェクトが設定されます。 if ($bookmark) 条件では、エントリが見つかったかどうかが確認されます。
  • データベースへの追加は、Cosmos DB 出力バインディングの名前 (newbookmark) と $newBookmark オブジェクトの値を指定して Push-OutputBinding を呼び出すのと同じくらいシンプルです。
  • キューへのメッセージの投稿は、キュー出力バインディングの名前 (newmessage) と $newBookmark オブジェクトの値を指定して Push-OutputBinding を呼び出すのと同じくらいシンプルです。

Note

行ったタスクは、キュー バインディングの作成のみです。 キューの作成は明示的に行っていません。 バインディングの機能を確認しましょう。 次の通知で宣言されているように、キューが存在しない場合、自動的に作成されます。

Screenshot showing UI tool tip that the queue will be auto-created.

これで終了です。 次のセクションで作業内容の動作を確認してみましょう。

試してみる

出力バインディングが複数あるので、テストはやや複雑になります。 前のユニットでは、クエリ文字列を含む HTTP 要求を送信し、テストして満足しましたが、今度は HTTP 投稿を実行する必要があります。 メッセージがキューに入っているかどうかを確認する必要もあります。

  1. HttpTrigger3 関数の [コード + テスト] ペインのコマンド バーで、[テスト/実行] を選択します。 新しいペインが表示され、次の図に示すように、[入力] タブが開きます。

    Screenshot showing the test/run pane.

  2. [HTTP メソッド] ドロップダウン リストで、[POST] が選択されていることを確認します。

  3. 要求本文の内容を、次の JSON オブジェクトに置き換えます。

    {
        "id": "docs",
        "url": "https://learn.microsoft.com/azure"
    }
    
  4. [実行] を選択します。

  5. [ログ] ペインに、プログラムの進行状況が表示されます。 完了したら、[出力] タブの [HTTP 応答コンテンツ] 設定に、"ブックマークは既に存在しています" と表示されていることを確認します。

    Screenshot of output tab showing bookmark already exists response.

    ブックマーク項目は、「演習 - 入力バインディングを使用してデータを読み取る」で追加しました。 応答では、var bookmark = context.bindings.bookmark JavaScript が正常に機能していることと、PowerShell コードが同じ接続を作成していることが確認されます。

  6. 2 つ目のブックマークをデータベースに POST しましょう。 [入力] タブを選択します。

  7. 要求本文の内容を、次の JSON オブジェクトに置き換えます。

    {
        "id": "github",
        "url": "https://www.github.com"
    }
    
  8. [実行] を選択します。

  9. 次のスクリーンショットに示すように、[出力] タブの、[HTTP 応答コンテンツ] に "ブックマークが追加されました" と表示されていることを確認します。

    Screenshot of output tab showing bookmark added response.

おめでとうございます。 関数は、設計したとおりに機能します。 でも、コードに追加したキュー操作はどうでしょうか。 キューに何か書き込まれたかどうかを確認してみましょう。

キューにメッセージが書き込まれたことを確認する

Azure Queue Storage キューは、ストレージ アカウントでホストされています。 出力バインディングの作成時にストレージ アカウントを構成しました。

  1. Azure portal のグローバル検索ボックスに「ストレージ アカウント」と入力し、結果リストで [ストレージ アカウント] を選択します。 [ストレージ アカウント] ペインが表示されます。

    Screenshot showing search results for Storage Account search.

  2. newmessage 出力バインディングを構成するために使用したストレージ アカウントを選択します。

  3. [ストレージ アカウント] メニューの [データ ストレージ] で、[キュー] を選択して、このストレージ アカウントでホストされているキューの一覧を表示します。 bookmarks-post-process キューが、次のスクリーンショットに示すように表示されていることを確認します。

    Screenshot showing queues hosted by this storage account.

  4. bookmarks-post-processを選択して、キュー内にあるメッセージを一覧表示します。 すべてが計画どおりに進んでいれば、ブックマークをデータベースに追加したときに投稿したメッセージがキューに含まれています。 次のような表示になります。

    Screenshot of message queue with two messages.

    この例では、メッセージに一意の ID が付与されており、[メッセージ テキスト] 列に、ご使用のブックマークが JSON 形式で表示されます。 データベースに既に存在していたため、追加しようとした Azure docs ブックマークのメッセージはありません。

  5. 関数をさらにテストするには、テスト ペイン内で、新しい id/url を設定して要求本文を変更し、関数を実行します。 このキューを見ると、さらにメッセージが届いているのがわかります。 また、データベースを参照することで、新しいエントリが追加されていることを確認できます。

この演習では、バインディングの知識を、出力バインディング、Azure Cosmos DB へのデータ書き込みまで広げました。 Azure キューにメッセージを投稿するための出力バインディングを追加しました。 この例では、データを成形してそれを受信ソースからさまざまな宛先に移動するのに役立つバインディングの真の力を示しています。 データベース コードの作成は行いませんでした。また、接続文字列の管理を自分で行う必要もありませんでした。 代わりに、バインディングを宣言によって構成しました。接続のセキュリティ保護、関数のスケーリング、接続のスケーリングはプラットフォームによって行われます。