Realtime Database-Trigger


Mit Cloud Functions können Sie Ereignisse in der Firebase Realtime Database, ohne dass der Clientcode aktualisiert werden muss. Mit Cloud Functions können Sie Realtime Database-Vorgänge mit vollem Verwaltungsaufwand ausführen Berechtigungen und stellt sicher, dass jede Änderung an Realtime Database verarbeitet wird. individuell anpassen. Sie können Firebase Realtime Database Änderungen vornehmen über das DataSnapshot oder über das Admin SDK.

In einem typischen Lebenszyklus führt eine Firebase Realtime Database-Funktion so vor:

  1. Wartet auf Änderungen an einem bestimmten Realtime Database-Standort.
  2. Wird ausgelöst, wenn ein Ereignis eintritt, und führt die zugehörigen Aufgaben aus (siehe Was kann ich tun mit Cloud Functions? finden Sie Beispiele für Anwendungsfälle).
  3. Sie empfängt ein Datenobjekt, das einen Snapshot der gespeicherten Daten enthält im angegebenen Dokument.

Realtime Database-Funktion auslösen

Neue Funktionen für Realtime Database-Ereignisse erstellen mit functions.database. Bis steuern, wann die Funktion ausgelöst wird, geben Sie einen der Event-Handler an und Geben Sie den Pfad Realtime Database an, unter dem auf Ereignisse überwacht wird.

Event-Handler festlegen

Mit Cloud Functions können Sie Realtime Database-Ereignisse mit zwei Spezifitätsgraden verarbeiten: Sie können gezielt nur nach Erstellungs-, Aktualisierungs- oder Löschereignissen oder nach beliebigen Änderungen jeglicher Art an einem Pfad Ausschau halten. Cloud Functions unterstützt die folgenden Ereignishandler für Realtime Database:

  • onWrite(): wird ausgelöst, wenn Daten in Realtime Database erstellt, aktualisiert oder gelöscht werden.
  • onCreate(), was ausgelöst wird, wenn in Realtime Database neue Daten erstellt werden
  • onUpdate(): Wird ausgelöst, wenn Daten in Realtime Database aktualisiert werden .
  • onDelete(), was ausgelöst wird, wenn Daten aus Realtime Database gelöscht werden .

Instanz und Pfad angeben

Rufen Sie ref(path) auf, um zu steuern, wann und wo Ihre Funktion ausgelöst werden soll. um einen Pfad und optional eine Realtime Database-Instanz anzugeben. mit instance('INSTANCE_NAME'). Wenn Sie keine Instanz angeben, wird die Funktion in der Standard-Realtime Database-Instanz für das Firebase-Projekt bereitgestellt. Beispiel:

  • Standardinstanz Realtime Database: functions.database.ref('/foo/bar')
  • Instanz namens „my-app-db-2“: functions.database.instance('my-app-db-2').ref('/foo/bar')

Diese Methoden weisen Ihre Funktion an, Schreibvorgänge unter einem bestimmten Pfad innerhalb Die Instanz Realtime Database. Die Pfadspezifikationen gleichen alle Schreibvorgänge ab, die einen Pfad betreffen. einschließlich Schreibvorgängen die irgendwo darunter passieren. Wenn Sie den Pfad Für Ihre Funktion als /foo/bar werden Ereignisse an diesen beiden Speicherorten abgeglichen:

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

In beiden Fällen geht Firebase davon aus, dass das Ereignis unter /foo/bar auftritt, und die Ereignisdaten enthalten die alten und neuen Daten unter /foo/bar. Bei großen Ereignisdaten Verwenden Sie mehrere Funktionen für tiefere Pfade anstelle eines einzelnen in der Nähe des Stammverzeichnisses Ihrer Datenbank. Für optimale Leistung sollten Sie Daten nur auf der untersten Ebene anfordern.

Sie können eine Pfadkomponente als Platzhalter angeben, indem Sie sie in geschweifte Klammern setzen Klammern; ref('foo/{bar}') stimmt mit jedem untergeordneten Element von /foo überein. Die Werte dieser Platzhalterpfadkomponenten sind innerhalb des EventContext.params-Objekts Ihrer Funktion verfügbar. In diesem Beispiel ist der Wert context.params.bar

Pfade mit Platzhaltern können mit mehreren Ereignissen aus einem einzigen Schreibvorgang übereinstimmen. Eine Einfügung von

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

entspricht zweimal dem Pfad "/foo/{bar}": einmal mit "hello": "world" und wieder mit "firebase": "functions".

Ereignisdaten verarbeiten

Bei der Verarbeitung eines Realtime Database-Ereignisses wird ein DataSnapshot Bei onWrite- oder onUpdate-Ereignissen ist der erste Parameter ein Change-Objekt mit zwei Snapshots, die den Datenstatus vor und nach dem auslösenden Ereignis darstellen. Für onCreate- und onDelete-Ereignisse: Das zurückgegebene Datenobjekt ist ein Snapshot der erstellten oder gelöschten Daten.

In diesem Beispiel ruft die Funktion den Snapshot für den angegebenen Pfad, wandelt den String an dieser Stelle in Großbuchstaben um und schreibt diesen geänderten String in die Datenbank:

// 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);
    });

Auf Informationen zur Nutzerauthentifizierung zugreifen

Von EventContext.auth und EventContext.authType, können Sie auf die Nutzerinformationen, einschließlich Berechtigungen, für den Nutzer, der die eine Funktion. Dies kann nützlich sein, um Sicherheitsregeln zu erzwingen, ermöglicht es Ihrer Funktion, verschiedene Vorgänge basierend auf dem Berechtigungsstufe:

const functions = require('firebase-functions/v1');
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);
      }
    });

Sie können sich auch mithilfe von Informationen zur Nutzerauthentifizierung ein Nutzer und Schreibvorgänge im Namen des Nutzers ausführen. Vergessen Sie nicht, die App-Instanz wie unten gezeigt, um Gleichzeitigkeitsprobleme zu vermeiden:

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));
      });
    });

Vorherigen Wert lesen

Das Change-Objekt hat einen before können Sie überprüfen, was Realtime Database vor der . Die Property before gibt einen DataSnapshot zurück, bei dem alle Methoden (z. B. val() und exists()) auf den vorherigen Wert verweisen. Sie können den neuen Wert entweder mit Original-DataSnapshot oder Lesen der after Property. Diese Property bei einer Change ist eine weitere DataSnapshot, die den Status der Daten nach dem Ereignis darstellt.

Beispielsweise kann das Attribut before verwendet werden, um dafür zu sorgen, dass die Funktion nur Text bei seiner Erstellung in Großbuchstaben:

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);
    });