演習 - 出力バインディングを使用してデータを書き込む
前の演習で、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 newmessage コードで使用するバインディング プロパティ。 キュー名 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
パラメーターを設定するのと同じくらいシンプルです。
Note
行ったタスクは、キュー バインディングの作成のみです。 キューの作成は明示的に行っていません。 バインディングの機能を確認しましょう。 次の通知で宣言されているように、キューが存在しない場合、自動的に作成されます。
。
<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
を呼び出すのと同じくらいシンプルです。
Note
行ったタスクは、キュー バインディングの作成のみです。 キューの作成は明示的に行っていません。 バインディングの機能を確認しましょう。 次の通知で宣言されているように、キューが存在しない場合、自動的に作成されます。
これで終了です。 次のセクションで作業内容の動作を確認してみましょう。
試してみる
出力バインディングが複数あるので、テストはやや複雑になります。 前のユニットでは、クエリ文字列を含む HTTP 要求を送信し、テストして満足しましたが、今度は HTTP 投稿を実行する必要があります。 メッセージがキューに入っているかどうかを確認する必要もあります。
HttpTrigger3 関数の [コード + テスト] ペインのコマンド バーで、[テスト/実行] を選択します。 新しいペインが表示され、次の図に示すように、[入力] タブが開きます。
[HTTP メソッド] ドロップダウン リストで、[POST] が選択されていることを確認します。
要求本文の内容を、次の JSON オブジェクトに置き換えます。
{ "id": "docs", "url": "https://learn.microsoft.com/azure" }
[実行] を選択します。
[ログ] ペインに、プログラムの進行状況が表示されます。 完了したら、[出力] タブの [HTTP 応答コンテンツ] 設定に、"ブックマークは既に存在しています" と表示されていることを確認します。
ブックマーク項目は、「演習 - 入力バインディングを使用してデータを読み取る」で追加しました。 応答では、
var bookmark = context.bindings.bookmark
JavaScript が正常に機能していることと、PowerShell コードが同じ接続を作成していることが確認されます。2 つ目のブックマークをデータベースに POST しましょう。 [入力] タブを選択します。
要求本文の内容を、次の 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 キューにメッセージを投稿するための出力バインディングを追加しました。 この例では、データを成形してそれを受信ソースからさまざまな宛先に移動するのに役立つバインディングの真の力を示しています。 データベース コードを記述したり、接続文字列を自分で管理したりする必要はありませんでした。 代わりに、バインディングを宣言によって構成しました。接続のセキュリティ保護、関数のスケーリング、接続のスケーリングはプラットフォームによって行われます。