一般的なライフサイクルでは、Firebase Realtime Database 関数は次のことを行います。
- 特定の Realtime Database パスへの変更を待機します。
- イベントが発生したときにトリガーし、そのタスクを実行します。
- そのパスに格納されているデータのスナップショットを含むデータ オブジェクトを受け取ります。
Firebase Realtime Database でのデータベース ノードの書き込み、作成、更新、または削除に応じて関数をトリガーできます。
Firebase Realtime Database の変更で関数をトリガーする
firebase-functions/v2/database
サブパッケージを使用して、Firebase Realtime Database イベントを処理する関数を作成します。関数がいつトリガーされるかを制御するには、イベント ハンドラーの 1 つを指定し、イベントをリッスンする Realtime Database パスを指定します。
関数の場所の設定
Realtime Database インスタンスの場所と関数の場所の間の距離によって、重大なネットワーク レイテンシが発生する可能性があります。また、リージョン間の不一致により、デプロイが失敗する可能性があります。このような状況を回避するには、データベース インスタンスの場所と一致するように関数の場所を指定します。
Realtime Database イベントの処理
関数を使用すると、Realtime Database イベントを 2 つのレベルの特異性で処理できます。特に書き込み、作成、更新、または削除イベントのみをリッスンすることも、参照に対するあらゆる種類の変更をリッスンすることもできます。
Realtime Database イベントに応答するための次のハンドラーを使用できます。
-
onValueWritten()
Realtime Database にデータが書き込まれたときにのみトリガーされます。 -
onValueCreated()
Realtime Database でデータが作成されたときにのみトリガーされます。 -
onValueUpdated()
Realtime Database でデータが更新されたときにのみトリガーされます。 -
onValueDeleted()
Realtime Database でデータが削除されたときにのみトリガーされます。
インスタンスとパスを指定
関数がいつ、どこでトリガーされるかを制御するには、関数にパスと、必要に応じて Realtime Database インスタンスを構成します。インスタンスを指定しない場合、関数は関数領域内のすべての Realtime Database インスタンスにデプロイされます。 Realtime Database インスタンス パターンを指定して、同じリージョン内の選択したインスタンスのサブセットにデプロイすることもできます。
たとえば、説明のためにonValueWritten()
を使用します。
# All Realtime Database instances in default function region us-central1 at path "/user/{uid}" # There must be at least one Realtime Database present in us-central1. const onwrittenfunctiondefault = onValueWritten("/user/{uid}", (event) => { // … }); # Instance named "my-app-db-2", at path "/user/{uid}". # The "my-app-db-2" instance must exist in this region. const onwrittenfunctioninstance = onValueWritten( { ref: "/user/{uid}", instance: "my-app-db-2" // This example assumes us-central1, but to set location: // region: "europe-west1" }, (event) => { // … } ); # Instance with "my-app-db-" prefix, at path "/user/{uid}", where uid ends with @gmail.com. # There must be at least one Realtime Database with "my-app-db-*" prefix in this region. const onwrittenfunctioninstance = onValueWritten( { ref: "/user/{uid=*@gmail.com}", instance: "my-app-db-*" // This example assumes us-central1, but to set location: // region: "europe-west1" }, (event) => { // … } );
これらのパラメーターは、Realtime Database インスタンス内の特定のパスで書き込みを処理するよう関数に指示します。
パスの仕様は、パスの下のどこかで発生する書き込みを含め、パスに触れるすべての書き込みに一致します。関数のパスを/foo/bar
として設定すると、次の両方の場所のイベントに一致します。
/foo/bar
/foo/bar/baz/really/deep/path
いずれの場合も、Firebase はイベントが/foo/bar
で発生し、イベント データには/foo/bar
の古いデータと新しいデータが含まれていると解釈します。イベント データが大きい可能性がある場合は、データベースのルートに近い単一の関数ではなく、より深いパスで複数の関数を使用することを検討してください。最高のパフォーマンスを得るには、可能な限り深いレベルのデータのみを要求してください。
ワイルドカードとキャプチャ
キャプチャには{key}
、 {key=*}
、 {key=prefix*}
、 {key=*suffix}
を使用できます。 *
、 prefix*
、 *suffix
。注: **
は、RTDB がサポートしていない複数セグメントのワイルドカードを表します。パス パターンを理解する を参照してください。
パスのワイルドカード。パス コンポーネントをワイルドカードとして指定できます。
- アスタリスク
*
を使用します。たとえば、foo/*
は、 foofoo/
の下のノード階層の 1 レベルにあるすべての子に一致します。 - アスタリスク
*
を正確に含むセグメントを使用します。たとえば、foo/app*-us
は、foofoo/
の下にapp
接頭辞と-us
接尾辞が付いたすべての子セグメントと一致します。
ワイルドカードを含むパスは、たとえば単一の書き込みからの複数のイベントに一致できます。の挿入
{
"foo": {
"hello": "world",
"firebase": "functions"
}
}
パス"/foo/*"
に 2 回一致します。1 回目は"hello": "world"
で、2 回目は"firebase": "functions"
です。
パスのキャプチャ。パスの一致を関数コードで使用する名前付き変数にキャプチャできます (例: /user/{uid}
、 /user/{uid=*-us}
)。
キャプチャ変数の値は、関数のdatabase.DatabaseEvent.paramsオブジェクト内で使用できます。
インスタンスのワイルドカード。ワイルドカードを使用してインスタンス コンポーネントを指定することもできます。インスタンスのワイルドカードには、プレフィックス、サフィックス、またはその両方を含めることができます (例: my-app-*-prod
)。
ワイルドカードとキャプチャ リファレンス
Cloud Functions (第 2 世代) と Realtime Database では、 ref
とinstance
を指定するときにパターンを使用できます。各トリガー インターフェイスには、関数のスコープを設定するための次のオプションがあります。
ref 指定 | instance の指定 | 行動 |
---|---|---|
シングル ( /foo/bar ) | 指定しない | 関数領域内のすべてのインスタンスにハンドラーのスコープを設定します。 |
シングル ( /foo/bar ) | 単一 ( 'my-new-db' ) | 関数領域内の特定のインスタンスにハンドラーのスコープを設定します。 |
シングル ( /foo/bar ) | パターン ( 'inst-prefix*' ) | 関数領域のパターンに一致するすべてのインスタンスにハンドラをスコープします。 |
パターン ( /foo/{bar} ) | 指定しない | 関数領域内のすべてのインスタンスにハンドラーのスコープを設定します。 |
パターン ( /foo/{bar} ) | 単一 ( 'my-new-db' ) | 関数領域内の特定のインスタンスにハンドラーのスコープを設定します。 |
パターン ( /foo/{bar} ) | パターン ( 'inst-prefix*' ) | 関数領域のパターンに一致するすべてのインスタンスにハンドラをスコープします。 |
イベント データの処理
Realtime Database イベントを処理する場合、返されるデータ オブジェクトはDataSnapshot
。
onValueWritten
またはonValueUpdated
イベントの場合、最初のパラメーターは、トリガー イベントの前後のデータ状態を表す 2 つのスナップショットを含むChange
オブジェクトです。
onValueCreated
およびonValueDeleted
イベントの場合、返されるデータ オブジェクトは、作成または削除されたデータのスナップショットです。
この例では、関数は指定されたパスfoo/bar
のスナップショットをsnap
として取得し、その場所の文字列を大文字に変換し、その変更された文字列をデータベースに書き込みます。
// Listens for new messages added to /messages/:pushId/original and creates an // uppercase version of the message to /messages/:pushId/uppercase export makeuppercase = onValueCreated("foo/bar", (event) => { // Grab the current value of what was written to the Realtime Database. const original = event.data.val(); functions.logger.log('Uppercasing', event.params.pushId, original); const uppercase = original.toUpperCase(); // You must return a Promise when performing asynchronous tasks inside a Functions such as // writing to the Firebase Realtime Database. // Setting an "uppercase" sibling in the Realtime Database returns a Promise. return event.data.ref.parent.child('uppercase').set(uppercase); });
前の値の読み取り
Change
オブジェクトにはbefore
プロパティがあり、イベントの前に Realtime Database に保存された内容を調べることができます。 before
プロパティは、すべてのメソッド ( val()
やexists()
など) が前の値を参照するDataSnapshot
を返します。元のDataSnapshot
を使用するか、 after
プロパティを読み取ることで、新しい値を再度読み取ることができます。 Change
のこのプロパティは、イベント発生後のデータの状態を表す別のDataSnapshot
。
たとえば、 before
プロパティを使用して、関数が最初に作成されたときにテキストのみを大文字にするようにすることができます。
exports makeuppercase = onValueWritten("/messages/{pushId}/original", (event) => { // Only edit data when it is first created. if (event.data.before.exists()) { return null; } // Exit when the data is deleted. if (!event.data.after.exists()) { return null; } // Grab the current value of what was written to the Realtime Database. const original = event.data.after.val(); console.log('Uppercasing', event.params.pushId, original); const uppercase = original.toUpperCase(); // You must return a Promise when performing asynchronous tasks inside a Functions such as // writing to the Firebase Realtime Database. // Setting an "uppercase" sibling in the Realtime Database returns a Promise. return event.data.after.ref.parent.child('uppercase').set(uppercase); });