Cloud Firestore 觸發條件


有了 Cloud Functions,您就能在 無需更新用戶端程式碼的 Cloud Firestore。 您可以透過 或是透過 Cloud 控制台 Admin SDK

在一般生命週期中,Cloud Firestore 函式會執行下列操作:

  1. 等待對特定文件的變更。
  2. 在事件發生時觸發並執行它的工作。
  3. 接收包含所儲存資料快照的資料物件 指定文件。如果是寫入或更新事件, 資料物件包含兩個快照,代表該之前的資料狀態 觸發事件

Firestore 執行個體位置與位置之間的距離 功能可能會造成網路延遲。為提高成效 請考慮指定函式位置,其中

Cloud Firestore 函式觸發條件

Cloud Functions for Firebase SDK 會匯出 functions.firestore 物件,可讓您建立繫結至特定 Cloud Firestore 事件的處理常式。

事件類型 觸發條件
onCreate 在第一次寫入文件時觸發。
onUpdate 在文件已經存在且已變更任何值時觸發。
onDelete 在刪除具有資料的文件時觸發。
onWrite 在觸發 onCreateonUpdateonDelete 時觸發。

如果您尚未啟用 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
    });

使用萬用字元指定一組文件

如果您想將觸發條件附加至一組文件,例如 特定集合,然後使用 {wildcard} 取代 文件 ID:

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

這個DocumentReference來自 Cloud 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 是在受信任的環境中執行,這代表 成為專案的服務帳戶您可以執行讀取和寫入 使用 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 觸發條件限制:

  • Cloud Functions (第 1 代) 必須符合現有的「(預設)」條件Vertex AI 原生模式沒有 支援 Cloud Firestore 具名資料庫或 Datastore 模式。請使用 Cloud Functions (第 2 代) 在這類情況下設定事件。
  • 我們不保證排序。快速變更可觸發下列時間中的函式叫用: 以免發生非預期的訂單
  • 事件至少會傳送一次,但單一事件可能會導致 多個函式叫用。避免取決於 僅須執行一次的機制 冪等函式
  • Cloud Firestore (Datastore 模式) 需要 Cloud Functions (第 2 代)Cloud Functions (第 1 代) 不會 支援 Datastore 模式
  • 觸發條件與單一資料庫相關聯。無法建立與多個資料庫相符的觸發條件。
  • 刪除資料庫不會自動刪除該資料庫的任何觸發條件。 觸發條件會停止傳送事件,但直到您刪除觸發條件為止。
  • 如果相符的事件超過請求大小上限, 事件可能不會傳送至 Cloud Functions (第 1 代)。
    • 因要求大小而未傳送的事件會記錄在平台記錄檔中 並會計入專案的記錄檔用量。
    • 您可以在記錄檔探索工具中找到這些記錄,並查看「事件無法傳送至 超出第 1 代限制的 Cloud 函式...」/error 嚴重性。您可以在 functionName 欄位下方找到函式名稱。如果 receiveTimestamp 欄位至今仍在一小時內,因此您可以推斷 閱讀相關文件,瞭解實際活動內容 是在時間戳記前後建立的快照
    • 如要避免這種展示頻率,可以採取下列做法:
      • 遷移並升級至 Cloud Functions (第 2 代)
      • 將文件縮小
      • 刪除有問題的 Cloud Functions
    • 您可以使用排除功能來關閉記錄功能 但請注意,違規活動將不會送達。