Firebase Summit で発表されたすべての情報をご覧ください。Firebase を使用してアプリ開発を加速し、自信を持ってアプリを実行する方法を紹介しています。詳細

CloudFirestoreトリガー

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

Cloud Functions を使用すると、クライアント コードを更新する必要なく、Cloud Firestore でイベントを処理できます。 DocumentSnapshotインターフェースまたはAdmin SDKを介して、Cloud Firestore の変更を行うことができます。

一般的なライフサイクルでは、Cloud Firestore 関数は次のことを行います。

  1. 特定のドキュメントへの変更を待ちます。
  2. イベントが発生したときにトリガーし、そのタスクを実行します (ユースケースの例については、Cloud Functions で何ができますか? を参照してください)。
  3. 指定されたドキュメントに格納されているデータのスナップショットを含むデータ オブジェクトを受け取ります。 onWriteまたはonUpdateイベントの場合、データ オブジェクトには、トリガー イベントの前後のデータ状態を表す 2 つのスナップショットが含まれます。

Firestore インスタンスの場所と関数の場所の間の距離により、重大なネットワーク レイテンシが発生する可能性があります。パフォーマンスを最適化するには、必要に応じて関数の場所を指定することを検討してください。

Cloud Firestore 関数のトリガー

Cloud Functions for Firebase SDK は、特定の Cloud Firestore イベントに関連付けられたハンドラを作成できるfunctions.firestoreオブジェクトをエクスポートします。

イベントタイプ引き金
onCreateドキュメントが初めて書き込まれたときにトリガーされます。
onUpdateドキュメントがすでに存在し、値が変更されたときにトリガーされます。
onDeleteデータを含むドキュメントが削除されたときにトリガーされます。
onWrite onCreateonUpdateまたはonDeleteがトリガーされたときにトリガーされます。

プロジェクトで Cloud Functions for Firebase をまだ有効にしていない場合は、 「はじめに: 最初の関数の作成とデプロイ」を読んで、Cloud Functions for Firebase プロジェクトを構成および設定してください。

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

関数トリガーを定義する

Cloud Firestore トリガーを定義するには、ドキュメント パスとイベント タイプを指定します。

Node.js

const functions = require('firebase-functions');

exports.myFunction = functions.firestore
  .document('my-collection/{docId}')
  .onWrite((change, context) => { /* ... */ });

ドキュメント パスは、特定のドキュメントまたはワイルドカード パターンのいずれかを参照できます。

単一のドキュメントを指定する

特定のドキュメントへ変更に対してイベントをトリガーする場合は、次の関数を使用できます。

Node.js

// Listen for any change on document `marie` in collection `users`
exports.myFunctionName = functions.firestore
    .document('users/marie').onWrite((change, context) => {
      // ... Your code here
    });

ワイルドカードを使用してドキュメントのグループを指定する

特定のコレクション内のドキュメントなど、ドキュメントのグループにトリガーをアタッチする場合は、ドキュメント ID の代わりに{wildcard}を使用します。

Node.js

// Listen for changes in all documents in the 'users' collection
exports.useWildcard = functions.firestore
    .document('users/{userId}')
    .onWrite((change, context) => {
      // If we set `/users/marie` to {name: "Marie"} then
      // context.params.userId == "marie"
      // ... and ...
      // change.after.data() == {name: "Marie"}
    });

この例では、 usersの任意のドキュメントの任意のフィールドが変更されると、 userIdというワイルドカードに一致します。

usersのドキュメントにサブコレクションがあり、それらのサブコレクションのドキュメントのいずれかのフィールドが変更された場合、 userIdワイルドカードはトリガーされません

ワイルドカードの一致はドキュメント パスから抽出され、 context.paramsに格納されます。ワイルドカードを好きなだけ定義して、明示的なコレクションまたはドキュメント ID を置き換えることができます。次に例を示します。

Node.js

// Listen for changes in all documents in the 'users' collection and all subcollections
exports.useMultipleWildcards = functions.firestore
    .document('users/{userId}/{messageCollectionId}/{messageId}')
    .onWrite((change, context) => {
      // If we set `/users/marie/incoming_messages/134` to {body: "Hello"} then
      // context.params.userId == "marie";
      // context.params.messageCollectionId == "incoming_messages";
      // context.params.messageId == "134";
      // ... and ...
      // change.after.data() == {body: "Hello"}
    });

イベントトリガー

新しいドキュメントが作成されたときに関数をトリガーする

ワイルドカードを指定したonCreate()ハンドラーを使用することで、コレクション内に新しいドキュメントが作成されるたびに、関数をトリガーして起動できます。この例の関数は、新しいユーザー プロファイルが追加されるたびにcreateUserを呼び出します。

Node.js

exports.createUser = functions.firestore
    .document('users/{userId}')
    .onCreate((snap, context) => {
      // Get an object representing the document
      // e.g. {'name': 'Marie', 'age': 66}
      const newValue = snap.data();

      // access a particular field as you would any JS property
      const name = newValue.name;

      // perform desired operations ...
    });

ドキュメントが更新されたときに関数をトリガーする

ワイルドカードを指定したonUpdate()関数を使用して、ドキュメントが更新されたときに起動する関数をトリガーすることもできます。この例の関数は、ユーザーがプロファイルを変更した場合にupdateUserを呼び出します。

Node.js

exports.updateUser = functions.firestore
    .document('users/{userId}')
    .onUpdate((change, context) => {
      // Get an object representing the document
      // e.g. {'name': 'Marie', 'age': 66}
      const newValue = change.after.data();

      // ...or the previous value before this update
      const previousValue = change.before.data();

      // access a particular field as you would any JS property
      const name = newValue.name;

      // perform desired operations ...
    });

ドキュメントが削除されたときに関数をトリガーする

ワイルドカードを指定したonDelete()関数を使用して、ドキュメントが削除されたときに関数をトリガーすることもできます。このサンプル関数は、ユーザーが自分のユーザー プロファイルを削除するときにdeleteUserを呼び出します。

Node.js

exports.deleteUser = functions.firestore
    .document('users/{userID}')
    .onDelete((snap, context) => {
      // Get an object representing the document prior to deletion
      // e.g. {'name': 'Marie', 'age': 66}
      const deletedValue = snap.data();

      // perform desired operations ...
    });

ドキュメントへのすべての変更に対して関数をトリガーする

発生するイベントのタイプを気にしない場合は、 onWrite()関数とワイルドカードを使用して、Cloud Firestore ドキュメントのすべての変更をリッスンできます。このサンプル関数は、ユーザーが作成、更新、または削除された場合に、 modifyUserを呼び出します。

Node.js

exports.modifyUser = functions.firestore
    .document('users/{userID}')
    .onWrite((change, context) => {
      // Get an object with the current document value.
      // If the document does not exist, it has been deleted.
      const document = change.after.exists ? change.after.data() : null;

      // Get an object with the previous document value (for update or delete)
      const oldDocument = change.before.data();

      // perform desired operations ...
    });

データの読み取りと書き込み

関数がトリガーされると、イベントに関連するデータのスナップショットが提供されます。このスナップショットを使用して、イベントをトリガーしたドキュメントの読み取りまたは書き込みを行ったり、Firebase Admin SDK を使用してデータベースの他の部分にアクセスしたりできます。

イベントデータ

データの読み取り

関数がトリガーされると、更新されたドキュメントからデータを取得したり、更新前にデータを取得したりすることができます。更新前のドキュメント スナップショットを含むchange.before.data()を使用して、以前のデータを取得できます。同様に、 change.after.data()には、更新後のドキュメント スナップショットの状態が含まれます。

Node.js

exports.updateUser2 = functions.firestore
    .document('users/{userId}')
    .onUpdate((change, context) => {
      // Get an object representing the current document
      const newValue = change.after.data();

      // ...or the previous value before this update
      const previousValue = change.before.data();
    });

他のオブジェクトと同じように、プロパティにアクセスできます。または、 get関数を使用して特定のフィールドにアクセスすることもできます。

Node.js

// Fetch data using standard accessors
const age = snap.data().age;
const name = snap.data()['name'];

// Fetch data using built in accessor
const experience = snap.get('experience');

データの書き込み

各関数呼び出しは、Cloud Firestore データベース内の特定のドキュメントに関連付けられています。関数に返されるスナップショットのrefプロパティでDocumentReferenceとしてそのドキュメントにアクセスできます。

このDocumentReferenceCloud Firestore Node.js SDKから取得され、 update()set()remove()などのメソッドが含まれているため、関数をトリガーしたドキュメントを簡単に変更できます。

Node.js

// Listen for updates to any `user` document.
exports.countNameChanges = functions.firestore
    .document('users/{userId}')
    .onUpdate((change, context) => {
      // Retrieve the current and previous value
      const data = change.after.data();
      const previousData = change.before.data();

      // We'll only update if the name has changed.
      // This is crucial to prevent infinite loops.
      if (data.name == previousData.name) {
        return null;
      }

      // Retrieve the current count of name changes
      let count = data.name_change_count;
      if (!count) {
        count = 0;
      }

      // Then return a promise of a set operation to update the count
      return change.after.ref.set({
        name_change_count: count + 1
      }, {merge: true});
    });

トリガー イベント外のデータ

Cloud Functions は信頼できる環境で実行されます。つまり、Cloud Functions はプロジェクトのサービス アカウントとして承認されます。 Firebase Admin SDKを使用して読み取りと書き込みを実行できます。

Node.js

const admin = require('firebase-admin');
admin.initializeApp();

const db = admin.firestore();

exports.writeToFirestore = functions.firestore
  .document('some/doc')
  .onWrite((change, context) => {
    db.doc('some/otherdoc').set({ ... });
  });

制限事項

Cloud Functions の Cloud Firestore トリガーに関する次の制限に注意してください。

  • 注文は保証されません。急激な変化は、予期しない順序で関数呼び出しをトリガーする可能性があります。
  • イベントは少なくとも 1 回配信されますが、1 つのイベントで複数の関数が呼び出される場合があります。 1 回限りのメカニズムに依存することは避け、冪等関数を記述します。
  • Cloud Functions の Cloud Firestore トリガーは、ネイティブ モードの Cloud Firestore でのみ使用できます。 Datastore モードの Cloud Firestore では使用できません。