即時資料庫觸發條件


有了 Cloud Functions,您就能處理 不必更新用戶端程式碼,也能使用 Firebase 即時資料庫。 Cloud Functions 可讓您透過完整的管理功能執行即時資料庫作業 權限,並確保系統能處理所有即時資料庫變更 個別。您可以透過以下項目,變更 Firebase 即時資料庫: DataSnapshot敬上 或透過 Admin SDK 下載。

在一般生命週期中,Firebase 即時資料庫函式會執行下列操作:

  1. 等待特定即時資料庫位置變更。
  2. 在事件發生時觸發並執行其工作 (請參閱我可以做些什麼? 該怎麼辦?。 用途)
  3. 接收包含所儲存資料快照的資料物件 指定文件。

觸發即時資料庫函式

為即時資料庫事件建立新函式 使用 functions.database。目的地: 控制函式觸發的時機、指定其中一個事件處理常式,以及 指定即時資料庫路徑來監聽事件。

設定事件處理常式

函式可讓您以兩種精細程度處理即時資料庫事件; 可監聽特定的建立、更新 或刪除路徑的任何類型變更 Cloud Functions 支援在即時資料庫中使用以下事件處理常式:

  • onWrite():在即時資料庫中建立、更新或刪除資料時觸發。
  • onCreate():在即時資料庫中建立新資料時觸發。
  • onUpdate():在即時資料庫中更新資料時觸發。
  • onDelete():從即時資料庫刪除資料時觸發。

指定執行個體和路徑

如要控管函式觸發的時機和位置,請呼叫 ref(path) 指定路徑,並選擇性地指定即時資料庫執行個體 搭配 instance('INSTANCE_NAME')。如果您不 會指定一個執行個體,函式會將該執行個體部署至預設的即時資料庫執行個體 Firebase 專案。例如:

  • 預設即時資料庫執行個體:functions.database.ref('/foo/bar')
  • 執行個體名稱為「my-app-db-2」:functions.database.instance('my-app-db-2').ref('/foo/bar')

這些方法會引導您的函式處理內部特定路徑的寫入作業 即時資料庫執行個體路徑規格會與接觸路徑的「所有」寫入作業相符。 包括寫入 呈現的成就如果將路徑設為 函式為 /foo/bar,會比對以下兩個位置的事件:

 /foo/bar
 /foo/bar/baz/really/deep/path

無論是哪一種情況,Firebase 都會解讀事件發生在 /foo/bar, 而事件資料包括 新舊資料 (/foo/bar)如果事件資料可能相當龐大 考慮在更深層的路徑中使用多個函式 函式。如要獲得最佳效能,請僅要求可能的最深層級資料。

您可以在路徑元件前後加上捲軸,將路徑元件指定為萬用字元 方括號;ref('foo/{bar}')/foo 的任何子項相符。這些屬性的值 萬用字元路徑元件位於 EventContext.params敬上 物件物件本例中的值是 context.params.bar

使用萬用字元的路徑可以與單一寫入內容中的多個事件進行比對。 將

{
  "foo": {
    "hello": "world",
    "firebase": "functions"
  }
}

比對路徑 "/foo/{bar}" 兩次:一次與 "hello": "world" 以及 "firebase": "functions" 的通訊。

處理事件資料

處理即時資料庫事件時,傳回的資料物件會是 DataSnapshot。 如果是 onWriteonUpdate 事件,則 第一個參數是含有兩個快照的 Change 物件 代表資料狀態的 觸發事件對於 onCreateonDelete 事件, 傳回的資料物件是建立或刪除資料的快照。

在這個範例中,函式會擷取 並將該位置的字串轉換成大寫, 並將經過修改的字串寫入資料庫:

// Listens for new messages added to /messages/:pushId/original and creates an
// uppercase version of the message to /messages/:pushId/uppercase
exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
    .onCreate((snapshot, context) => {
      // Grab the current value of what was written to the Realtime Database.
      const original = snapshot.val();
      functions.logger.log('Uppercasing', context.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 snapshot.ref.parent.child('uppercase').set(uppercase);
    });

存取使用者驗證資訊

來源:EventContext.authEventContext.authType, 您可以存取 針對觸發事件的使用者資訊 (包括權限) 函式這對於強制執行安全性規則、 讓您的函式依照使用者的 權限等級:

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

exports.simpleDbFunction = functions.database.ref('/path')
    .onCreate((snap, context) => {
      if (context.authType === 'ADMIN') {
        // do something
      } else if (context.authType === 'USER') {
        console.log(snap.val(), 'written by', context.auth.uid);
      }
    });

您也可以利用使用者驗證資訊來「冒用」身分使用者 並代表使用者執行寫入作業請務必刪除 應用程式執行個體,如下所示:

exports.impersonateMakeUpperCase = functions.database.ref('/messages/{pushId}/original')
    .onCreate((snap, context) => {
      const appOptions = JSON.parse(process.env.FIREBASE_CONFIG);
      appOptions.databaseAuthVariableOverride = context.auth;
      const app = admin.initializeApp(appOptions, 'app');
      const uppercase = snap.val().toUpperCase();
      const ref = snap.ref.parent.child('uppercase');

      const deleteApp = () => app.delete().catch(() => null);

      return app.database().ref(ref).set(uppercase).then(res => {
        // Deleting the app is necessary for preventing concurrency leaks
        return deleteApp().then(() => res);
      }).catch(err => {
        return deleteApp().then(() => Promise.reject(err));
      });
    });

讀取先前的值

Change 物件有 before 屬性,方便您查看先前儲存至即時資料庫的內容, 活動。before 屬性會傳回 DataSnapshot,其中所有 方法 (例如 val()exists())。 參照先前的值您可以使用下列任一方法 原始 DataSnapshot,或是參閱 after 資源。任何 Change 上的這個屬性,是另一個代表 DataSnapshot 資料在事件發生「之後」的狀態。

例如,使用 before 屬性可確保只有函式 大寫文字:

exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
    .onWrite((change, context) => {
      // Only edit data when it is first created.
      if (change.before.exists()) {
        return null;
      }
      // Exit when the data is deleted.
      if (!change.after.exists()) {
        return null;
      }
      // Grab the current value of what was written to the Realtime Database.
      const original = change.after.val();
      console.log('Uppercasing', context.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 change.after.ref.parent.child('uppercase').set(uppercase);
    });