Join us for Firebase Summit on November 10, 2021. Tune in to learn how Firebase can help you accelerate app development, release with confidence, and scale with ease. Register

Déclencheurs de base de données

Avec Cloud Functions, vous pouvez gérer les événements dans la base de données en temps réel Firebase sans avoir besoin de mettre à jour le code client. Cloud Functions vous permet d'exécuter des opérations de base de données en temps réel avec des privilèges administratifs complets et garantit que chaque modification apportée à la base de données en temps réel est traitée individuellement. Vous pouvez faire Firebase en temps réel des modifications de la base de données via le DataSnapshot ou via le SDK d' administration .

Dans un cycle de vie typique, une fonction de base de données en temps réel Firebase effectue les opérations suivantes :

  1. Attend les modifications apportées à un emplacement particulier de la base de données en temps réel.
  2. Déclencheurs lorsqu'un événement se produit et exécute ses tâches (voir Que puis - je faire avec les fonctions Cloud? Des exemples de cas d'utilisation).
  3. Reçoit un objet de données qui contient un instantané des données stockées dans le document spécifié.

Déclencher une fonction de base de données en temps réel

Créer de nouvelles fonctions pour les événements de base de données en temps réel avec functions.database . Pour contrôler le moment où la fonction se déclenche, spécifiez l'un des gestionnaires d'événements et spécifiez le chemin de la base de données en temps réel où elle écoutera les événements.

Définir le gestionnaire d'événements

Les fonctions vous permettent de gérer les événements de la base de données en temps réel à deux niveaux de spécificité ; vous pouvez écouter uniquement les événements de création, de mise à jour ou de suppression, ou vous pouvez écouter toute modification de quelque nature que ce soit d'un chemin. Cloud Functions est compatible avec les gestionnaires d'événements suivants pour Realtime Database :

  • onWrite() , qui se déclenche lorsque des données sont créés, mis à jour ou supprimés dans la base de données en temps réel.
  • onCreate() , qui se déclenche lorsque de nouvelles données est créé dans la base de données en temps réel.
  • onUpdate() , qui déclenche lorsque les données sont mises à jour en temps réel la base de données.
  • onDelete() , ce qui déclenche lorsque les données sont supprimées de la base de données en temps réel.

Spécifier l'instance et le chemin

Pour le contrôle quand et où votre fonction doit déclencher, appel ref(path) pour spécifier un chemin, et éventuellement spécifier une instance de base de données en temps réel avec instance('INSTANCE_NAME') . Si vous ne spécifiez pas d'instance, la fonction se déploie sur l'instance de base de données en temps réel par défaut pour le projet Firebase. Par exemple :

  • Instance par défaut en temps réel de la base de données: functions.database.ref('/foo/bar')
  • Instance nommée "my-app-db-2": functions.database.instance('my-app-db-2').ref('/foo/bar')

Ces méthodes ordonnent à votre fonction de gérer les écritures sur un certain chemin au sein de l'instance de la base de données en temps réel. Path specifications correspondent à toutes les écritures qui touchent un chemin, y compris les écritures qui se produisent partout en dessous. Si vous définissez le chemin de votre fonction /foo/bar , elle correspond à un événement dans ces deux endroits:

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

Dans les deux cas, Firebase interprète que l'événement se produit à /foo/bar , et les données d'événement comprend les anciens et les nouvelles données à /foo/bar . Si les données d'événement peuvent être volumineuses, envisagez d'utiliser plusieurs fonctions à des chemins plus profonds au lieu d'une seule fonction près de la racine de votre base de données. Pour des performances optimales, demandez uniquement des données au niveau le plus profond possible.

Vous pouvez spécifier un composant de chemin en tant que caractère générique en l'entourant d'accolades ; ref('foo/{bar}') correspond à tout enfant de /foo . Les valeurs de ces composants de chemin génériques sont disponibles dans le EventContext.params objet de votre fonction. Dans cet exemple, la valeur est disponible en context.params.bar .

Les chemins avec des caractères génériques peuvent correspondre à plusieurs événements à partir d'une seule écriture. Un insert de

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

correspond au chemin "/foo/{bar}" deux fois: une fois avec "hello": "world" et à nouveau avec "firebase": "functions" .

Gérer les données d'événement

Lors de la manipulation d' un événement de base de données en temps réel, l'objet de données renvoyé est un DataSnapshot . Pour onWrite ou onUpdate événements, le premier paramètre est un Change objet qui contient deux instantanés qui représentent l'état de données avant et après l'événement de déclenchement. Pour onCreate et onDelete événements, l'objet de données renvoyé est un instantané des données créées ou supprimées.

Dans cet exemple, la fonction récupère l'instantané pour le chemin d' accès spécifié comme snap , convertit la chaîne à cet endroit en majuscules, et écrit cette chaîne modifiée à la base de données:

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

Accéder aux informations d'authentification de l'utilisateur

De EventContext.auth et EventContext.authType , vous pouvez accéder aux informations de l' utilisateur, y compris les autorisations, pour l'utilisateur qui a déclenché une fonction. Cela peut être utile pour appliquer des règles de sécurité, permettant à votre fonction d'effectuer différentes opérations en fonction du niveau d'autorisations de l'utilisateur :

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

En outre, vous pouvez exploiter les informations d'authentification de l'utilisateur pour « emprunter l'identité » d'un utilisateur et effectuer des opérations d'écriture au nom de l'utilisateur. Assurez-vous de supprimer l'instance d'application comme indiqué ci-dessous afin d'éviter les problèmes de simultanéité :

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

Lecture de la valeur précédente

Le Change objet a une before la propriété que vous permet d' inspecter ce qui a été enregistré dans la base de données en temps réel avant l'événement. La before propriété renvoie une DataSnapshot où toutes les méthodes (par exemple, val() et exists() ) se réfèrent à la valeur précédente. Vous pouvez lire la nouvelle valeur à nouveau en utilisant soit l'original DataSnapshot ou la lecture after la propriété. Cette propriété sur tout Change est une autre DataSnapshot représentant l'état des données après l'événement a eu lieu.

Par exemple, l' before propriété peut être utilisée pour vous assurer que la fonction que du texte en majuscule lors de sa création:

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