演習 - 出力バインディングを使用してデータを書き込む
前の演習で、Azure Cosmos DB データベース内のブックマークを検索するシナリオを実装しました。 このブックマークのコレクションからデータを読み取るように入力バインディングを構成しました。 しかし、できることはもっとたくさんあります。 シナリオを拡張して書き込みも行ってみましょう。 次のフローチャートについて考えてみます。
このシナリオでは、コレクションにブックマークを追加する要求を受信します。 この要求によって、目的のキーまたは ID がブックマーク URL と共に渡されます。 フローチャート内で確認できるように、そのキーがバックエンド内に既に存在する場合はエラーで応答します。
渡されたキーが見つからない場合は、新しいブックマークをデータベースに追加します。 それで終わりにしてもかまいませんが、もう少しやってみましょう。
フローチャート内の別の手順に気付きましたか? これまで、処理の観点からは受信したデータに対して大したことは行いませんでした。 受信した内容をデータベースに移動します。 ただし、実際のソリューションでは、そのデータを何らかの方法で処理するでしょう。 すべての処理を同じ関数で実行できます。 ただし、この演習では、別のコンポーネントまたはビジネス ロジックにさらに処理をオフロードするパターンを示します。
このブックマーク シナリオでの作業のオフロードを示す良い例として、どのようなものが考えられるでしょうか? 新しいブックマークを QR コード生成サービスに送信するというのはどうでしょう? このサービスでは、URL の QR コードが生成され、Blob Storage に画像が格納され、QR イメージのアドレスがブックマーク コレクションのエントリに追加されます。 QR イメージを生成するサービスの呼び出しには時間がかかります。 そのため、結果を待つ代わりに、タスクを関数に渡し、このタスクを非同期的に完了させます。
Azure Functions では、さまざまな統合ソースに対して入力バインディングがサポートされているのと同様に、出力バインディング用のテンプレートのセットも用意されています。そのため、データ ソースへのデータの書き込みを容易に行うことができます。 出力バインディングは、function.json ファイルでも構成されています。 この演習で示すように、複数のデータ ソースとサービスを操作するように関数を構成できます。
重要
この演習では、サンドボックスのリソースとこれまでのユニットで作成したリソース (具体的には、Azure Cosmos DB データベース、ブックマーク、入力バインディング) を基にします。 前のユニットで演習を完了していない場合は、この演習を完了できません。
HTTP によってトリガーされる関数を作成する
Azure portal で、HttpTrigger2 関数ページの上部にある階層リンク パスで関数アプリの名前を選択して、作成した関数アプリにアクセスします。
[概要] ページの [関数] タブには、作成した HTTP トリガー関数が表示されているはずです。
[関数] タブの [作成] を選択します。[関数の作成] ペインが表示されます。
[ テンプレートの選択 ] セクションで、[ HTTP トリガー] を選択し、[ 次へ] を選択します。 [テンプレートの詳細] タブで既定値を受け入れ、[作成] を選択します。 HttpTrigger3 関数の [概要] ペインが表示されます。
Azure Cosmos DB 入力バインディングを追加する
Azure Cosmos DB 入力バインディングをもう 1 つ追加しましょう。
HttpTrigger3 関数メニューで、[統合] を選択します。 [統合] ペインが表示されます。
[トリガーと入力] ボックスで、[入力の追加] を選択します。 [入力の作成] ペインが表示されます。
[バインドの種類] ドロップダウン リストで、[Azure Cosmos DB] を選択します。
[Cosmos DB アカウント接続] 設定には、前の演習で作成した接続が事前入力されています。
接続が一覧表示されない場合は、次の手順に従って新しい接続を作成します。
[Azure Cosmos DB の詳細] セクションの [Cosmos DB アカウント接続] 設定で、[新規] リンクを選択します。
[新しい Cosmos DB 接続] ダイアログ ボックスが表示されたら、[OK] を選択して接続を作成します。 新しい Cosmos DB アカウント接続が作成されます。
このペインのその他の設定に、次の値を入力します。 設定の目的の詳細を確認するには、右側にある情報アイコンをいつでも選択できます。
設定 値 説明 ドキュメント パラメーター名 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 (見つかった) ドキュメントを返します。
[追加] を選択して、入力バインディング構成を保存します。
これで Azure Cosmos DB 入力バインディングが用意されました。 新しいエントリをコレクションに書き込むことができるように、出力バインディングを追加しましょう。
Azure Cosmos DB の出力バインディングの追加
HttpTrigger3 の [統合] ペインの [出力] ボックスで、[出力の追加] を選択します。 [出力の作成] ペインが表示されます。
[バインドの種類] の下のドロップダウン リストから、[Azure Cosmos DB] を選択します。
[Cosmos DB アカウント接続] 設定には、先ほど作成した接続が事前入力されているはずです。 そうでない場合は、ドロップダウン リストを展開し、HttpTrigger3 入力バインドに定義した接続を選択します。
出力バインディングの残りの設定に、次の値を入力します。
設定 値 説明 ドキュメント パラメーター名 newbookmark
コードでこのバインディングを識別するための名前。 このパラメーターは新しいブックマーク エントリを書き込むために使用されます。 データベース名 func-io-learn-db
使用するデータベース。 この値は、このレッスンで以前に設定したデータベース名です。 コレクション名 Bookmarks
データの読み取り元のコレクションの名前。 この値は、レッスンの前半で定義したコンテナー名です。 パーティション キー /id
前の手順で Bookmarks Azure Cosmos DB コンテナーを作成したときに定義したパーティション キーを追加します。 ここに入力するキー (入力バインディング構成 <key>
で指定) は、コンテナー内のキーと一致する必要があります。[追加] を選択して、この出力バインディング構成を保存します。
これで、コレクションから読み込むためのバインディングとコレクションに書き込むためのバインディングを用意できました。
Azure Queue Storage 出力バインディングを追加する
Azure Queue Storage は、世界中のどこからでもアクセスできるメッセージを格納するためのサービスです。 単一のメッセージのサイズは 64 KB ほどになります。キューには、キューが定義されているストレージ アカウントの合計容量に達するまで、数百万件のメッセージを格納できます。この合計容量はストレージ アカウントで定義されています。 次の図は、このシナリオでのキューの使用方法の概要を示します。
この例では、 add-bookmark という名前の関数がキューにメッセージを追加し、別の名前の gen-qr-code が同じキューからメッセージをポップして要求を処理することがわかります。 add-bookmark からキューにメッセージを書き込む ("プッシュする") ので、新しい出力バインドをソリューションに追加します。
ポータルから、バインドを作成しましょう。
関数の [統合] ペインの [出力] ボックスで、[出力の追加] を選択します。 [出力の作成] ペインが表示されます。
[バインドの種類] ドロップダウン リストで、[Azure Queue Storage] を選択します。
Microsoft.Azure.WebJobs.Extensions.Storage
拡張機能をインストールするように求めるメッセージが表示されたら、[インストール] を選択し、インストールが完了するまで待ちます。
次に、キューをホストするストレージ アカウント接続を設定します。
[ストレージ アカウント接続] で、[新規] を選択します。 [新しいストレージ アカウント接続] ダイアログ ボックスが表示されます。
このモジュールの最初に、関数アプリを作成したときに、ストレージ アカウントも作成されました。 それをドロップダウン リストから選択し、[OK] を選択します。
[ストレージ アカウント接続] 設定には、接続の名前が設定されます。
既定値のままにしておくこともできますが、残りのプロパティにより意味を持たせるために設定をいくつか変更しましょう。
[出力の作成] ペインで、次の古い値を新しい値に置き換えて設定を完成させます。
設定 古い値 新しい値 説明 メッセージ パラメーター名 outputQueueItem 新しいメッセージ コードで使用するバインディング プロパティ。 キュー名 outqueue bookmarks-post-process 別の関数が追加の処理を行えるようにブックマークを配置するキューの名前です。 [追加] を選択して、Azure Queue Storage の出力構成を保存します。
関数の実装を更新する
これで、すべてのバインドがセットアップされました。 それらをこの関数で使ってみましょう。
コード エディターで index.js ファイルを開くには、 関数 HttpTrigger3 を選択します。
メニューで、[コードとテスト] を選択します。 関数の [コードとテスト] ペインが表示されます。
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
パラメーターを設定するだけとシンプルです。
注
行ったタスクは、キュー バインディングの作成のみです。 明示的にキューを作成することはしていません。 これこそがバインディングの優れた機能です。 次の通知で宣言されているように、キューが存在しない場合、自動的に作成されます。
<functionapp> \ HttpTrigger3 \
パスのドロップダウン リストから function.json を選択し、次の変更を行います。"collectionName"
のすべてのインスタンスを"containerName"
に変更します。"connectionStringSetting"
のすべてのインスタンスを"connection"
に変更します。"methods": []
への参照を削除します。
最終的な function.json ファイルは、次のコードのようになります。
{ "bindings": [ { "authLevel": "function", "type": "httpTrigger", "direction": "in", "name": "req", "methods": [ "get", "post" ] }, { "type": "http", "direction": "out", "name": "res" }, { "name": "bookmark", "direction": "in", "type": "cosmosDB", "partitionKey": "{id}", "databaseName": "func-io-learn-db", "containerName": "Bookmarks", "connection": "your-database_DOCUMENTDB", "id": "{id}" }, { "name": "newbookmark", "direction": "out", "type": "cosmosDB", "partitionKey": "/id", "databaseName": "func-io-learn-db", "containerName": "Bookmarks", "connection": "your-database_DOCUMENTDB" }, { "name": "newmessage", "direction": "out", "type": "queue", "queueName": "bookmarks-post-process", "connection": "your-storage-account_STORAGE" } ] }
コマンド バーの [保存] を選択します。
これで終了です。 行った作業について、次のセクションで動作を確認しましょう。
コード エディターで run.ps1 ファイルを開くには、ペインの上部にある階層リンクから HttpTrigger3 関数を選択します。
[関数] メニューで、[ コード + テスト] を選択します。 HttpTrigger3 関数の[コードとテスト] ペインが表示され、run.ps1 の既定の内容が表示されます。
このファイルの内容を次のコードに置き換えます。
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" })
コマンド バーの [保存] を選択します。 接続が確立され、ログ ファイル セッションが開かれます。
このコードで何が行われるのかを詳しく見てみましょう。
- この関数はデータを変更するため、HTTP 要求は POST であり、ブックマーク データは要求本文の一部であると想定しています。
- Azure Cosmos DB の入力バインディングは、要求内の
id
を使用して、ドキュメント (ブックマーク) を取得しようとします。 エントリが見つかると、bookmark
オブジェクトが設定されます。if ($bookmark)
条件では、エントリが見つかったかどうかが確認されます。 - データベースへの追加は、Cosmos DB 出力バインディングの名前 (
newbookmark
) と$newBookmark
オブジェクトの値を指定してPush-OutputBinding
を呼び出すのと同じくらいシンプルです。 - キューへのメッセージの投稿は、キュー出力バインディングの名前 (
newmessage
) と$newBookmark
オブジェクトの値を指定してPush-OutputBinding
を呼び出すのと同じくらいシンプルです。
注
行ったタスクは、キュー バインディングの作成のみです。 明示的にキューを作成することはしていません。 これこそがバインディングの優れた機能です。 次の通知で宣言されているように、キューが存在しない場合、自動的に作成されます。
これで終了です。 次のセクションで作業内容の動作を確認してみましょう。
試してみる
出力バインディングが複数あるので、テストはやや複雑になります。 前のユニットでは、クエリ文字列を含む HTTP 要求を送信し、テストして満足しましたが、今度は HTTP 投稿を実行する必要があります。 メッセージがキューに入っているかどうかを確認する必要もあります。
HttpTrigger3 関数の [コードとテスト] ウィンドウのコマンド バーで、[テスト/実行] を選択します。 新しいペインが表示され、次の図に示すように、[入力] タブが開きます。
[HTTP メソッド] ドロップダウン リストで、[POST] が選択されていることを確認します。
要求本文の内容を、次の JSON オブジェクトに置き換えます。
{ "id": "docs", "url": "https://learn.microsoft.com/azure" }
[実行] を選択します。
[ログ] ペインに、プログラムの進行状況が表示されます。 完了したら、[ 出力 ] タブに ブックマークが既に表示 されていることを確認します。 HTTP 応答のコンテンツ 設定で確認します。
ブックマーク項目は、「演習 - 入力バインディングを使用してデータを読み取る」で追加しました。 応答では、
var bookmark = context.bindings.bookmark
JavaScript が正常に機能していることと、PowerShell コードが同じ接続を作成していることが確認されます。2 つ目のブックマークをデータベースに配置しましょう。 [入力] タブを選択します。
要求本文の内容を、次の JSON オブジェクトに置き換えます。
{ "id": "github", "url": "https://www.github.com" }
[実行] を選択します。
次のスクリーンショットに示すように、[ 出力 ] タブに[ ブックマークが追加されました! ] が HTTP 応答コンテンツに表示されることを確認します。
これで、関数は設計どおりに動作します。 しかし、コードに追加したキュー操作はどうでしょうか。 キューに何か書き込まれたかどうかを確認してみましょう。
キューにメッセージが書き込まれたことを確認する
Azure Queue Storage キューは、ストレージ アカウントでホストされています。 出力バインディングの作成時にストレージ アカウントを構成しました。
Azure portal のグローバル検索バーで、 ストレージ アカウントを入力します。 次に、結果の一覧で [ ストレージ アカウント] を選択します。 [ストレージ アカウント] ペインが表示されます。
newmessage 出力バインディングを構成するために使用したストレージ アカウントを選択します。
[ストレージ アカウント] メニューの [データ ストレージ] で、[キュー] を選択して、このストレージ アカウントでホストされているキューの一覧を表示します。 bookmarks-post-process キューが、次のスクリーンショットに示すように表示されていることを確認します。
bookmarks-post-process を選択して、キュー内にあるメッセージを一覧表示します。 すべてが計画どおりに進んでいれば、ブックマークをデータベースに追加したときに投稿したメッセージがキューに含まれています。 つまり、次のようになります。
この例では、メッセージに一意の ID が付与されており、[メッセージ テキスト] 列に、ブックマークが JSON 形式で表示されます。 データベースに既に存在していたため、追加しようとした Azure
docs
ブックマークのメッセージはありません。新しい ID/URL セットを使用してテスト ウィンドウの要求本文を変更し、関数を実行することで、関数をさらにテストできます。 このキューを見ると、さらにメッセージが届いているのがわかります。 また、データベースを参照することで、新しいエントリが追加されていることを確認できます。
この演習では、出力バインドへのバインドと Azure Cosmos DB へのデータの書き込みに関する知識を拡張しました。 Azure キューにメッセージを投稿するための出力バインディングを追加しました。 この例では、データを成形してそれを受信ソースからさまざまな宛先に移動するのに役立つバインディングの真の力を示しています。 データベース コードを記述したり、接続文字列を自分で管理したりする必要はありませんでした。 代わりに、バインドを宣言的に構成し、接続のセキュリティ保護、関数のスケーリング、接続のスケーリングをプラットフォームで行うことができます。