Déclencheurs Cloud Firestore

Avec Cloud Functions, vous pouvez gérer des événements dans Cloud Firestore sans avoir à mettre à jour le code client. Vous pouvez apporter des modifications à Cloud Firestore via l'interface DocumentSnapshot ou via le SDK Admin .

Dans un cycle de vie typique, une fonction Cloud Firestore effectue les opérations suivantes :

  1. Attend les modifications apportées à un document particulier.
  2. Se déclenche lorsqu'un événement se produit et exécute ses tâches (voir Que puis-je faire avec Cloud Functions ? pour 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é. Pour les événements onWrite ou onUpdate , l'objet de données contient deux instantanés qui représentent l'état des données avant et après l'événement déclencheur.

La distance entre l'emplacement de l'instance Firestore et l'emplacement de la fonction peut créer une latence réseau importante. Pour optimiser les performances, envisagez de spécifier l' emplacement de la fonction, le cas échéant.

Déclencheurs de fonction Cloud Firestore

Le SDK Cloud Functions for Firebase exporte un objet functions.firestore qui vous permet de créer des gestionnaires liés à des événements Cloud Firestore spécifiques.

Type d'événement Gâchette
onCreate Déclenché lorsqu'un document est écrit pour la première fois.
onUpdate Déclenché lorsqu'un document existe déjà et qu'une valeur a été modifiée.
onDelete Déclenché lorsqu'un document contenant des données est supprimé.
onWrite Déclenché lorsque onCreate , onUpdate ou onDelete est déclenché.

Si vous n'avez pas encore de projet activé pour Cloud Functions pour Firebase, lisez Premiers pas : Écrivez et déployez vos premières fonctions pour configurer et configurer votre projet Cloud Functions pour Firebase.

Écrire des fonctions déclenchées par Cloud Firestore

Définir un déclencheur de fonction

Pour définir un déclencheur Cloud Firestore, spécifiez un chemin de document et un type d'événement :

Node.js

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

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

Les chemins d'accès aux documents peuvent faire référence à un document spécifique ou à un modèle générique .

Spécifiez un seul document

Si vous souhaitez déclencher un événement pour toute modification apportée à un document spécifique, vous pouvez utiliser la fonction suivante.

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

Spécifier un groupe de documents à l'aide de caractères génériques

Si vous souhaitez attacher un déclencheur à un groupe de documents, comme n'importe quel document d'une certaine collection, utilisez un {wildcard} à la place de l'ID de document :

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

Dans cet exemple, lorsqu'un champ de n'importe quel document dans users est modifié, il correspond à un caractère générique appelé userId .

Si un document dans users a des sous-collections et qu'un champ dans l'un des documents de ces sous-collections est modifié, le caractère générique userId n'est pas déclenché.

Les correspondances génériques sont extraites du chemin du document et stockées dans context.params . Vous pouvez définir autant de caractères génériques que vous le souhaitez pour remplacer des ID de collection ou de document explicites, par exemple :

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

Déclencheurs d'événements

Déclencher une fonction lorsqu'un nouveau document est créé

Vous pouvez déclencher une fonction pour qu'elle se déclenche à chaque fois qu'un nouveau document est créé dans une collection en utilisant un gestionnaire onCreate() avec un joker . Cet exemple de fonction appelle createUser chaque fois qu'un nouveau profil utilisateur est ajouté :

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

Déclencher une fonction lorsqu'un document est mis à jour

Vous pouvez également déclencher le déclenchement d'une fonction lorsqu'un document est mis à jour à l'aide de la fonction onUpdate() avec un joker . Cet exemple de fonction appelle updateUser si un utilisateur modifie son profil :

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

Déclencher une fonction lorsqu'un document est supprimé

Vous pouvez également déclencher une fonction lorsqu'un document est supprimé en utilisant la fonction onDelete() avec un joker . Cet exemple de fonction appelle deleteUser lorsqu'un utilisateur supprime son profil utilisateur :

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

Déclencher une fonction pour toutes les modifications apportées à un document

Si vous ne vous souciez pas du type d'événement déclenché, vous pouvez écouter toutes les modifications apportées à un document Cloud Firestore à l'aide de la fonction onWrite() avec un caractère générique . Cet exemple de fonction appelle modifyUser si un utilisateur est créé, mis à jour ou supprimé :

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

Lecture et écriture de données

Lorsqu'une fonction est déclenchée, elle fournit un instantané des données liées à l'événement. Vous pouvez utiliser cet instantané pour lire ou écrire dans le document qui a déclenché l'événement, ou utiliser le SDK Firebase Admin pour accéder à d'autres parties de votre base de données.

Données d'événement

Lecture de données

Lorsqu'une fonction est déclenchée, vous souhaiterez peut-être obtenir les données d'un document qui a été mis à jour ou obtenir les données avant la mise à jour. Vous pouvez obtenir les données précédentes en utilisant change.before.data() , qui contient l'instantané du document avant la mise à jour. De même, change.after.data() contient l'état de l'instantané du document après la mise à jour.

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

Vous pouvez accéder aux propriétés comme vous le feriez dans n'importe quel autre objet. Vous pouvez également utiliser la fonction get pour accéder à des champs spécifiques :

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

Écrire des données

Chaque invocation de fonction est associée à un document spécifique dans votre base de données Cloud Firestore. Vous pouvez accéder à ce document en tant que DocumentReference dans la propriété ref de l'instantané renvoyé à votre fonction.

Cette DocumentReference provient du SDK Cloud Firestore Node.js et inclut des méthodes telles que update() , set() et remove() afin que vous puissiez facilement modifier le document qui a déclenché la fonction.

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

Données en dehors de l'événement déclencheur

Les fonctions Cloud s'exécutent dans un environnement de confiance, ce qui signifie qu'elles sont autorisées en tant que compte de service sur votre projet. Vous pouvez effectuer des lectures et des écritures à l'aide du SDK Firebase Admin :

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({ ... });
  });

Limites

Notez les limitations suivantes pour les déclencheurs Cloud Firestore pour Cloud Functions :

  • La commande n'est pas garantie. Des changements rapides peuvent déclencher des appels de fonction dans un ordre inattendu.
  • Les événements sont livrés au moins une fois, mais un seul événement peut entraîner plusieurs appels de fonction. Évitez de dépendre de la mécanique exactement une fois et écrivez des fonctions idempotentes .
  • Les déclencheurs Cloud Firestore pour Cloud Functions sont disponibles uniquement pour Cloud Firestore en mode natif . Il n'est pas disponible pour Cloud Firestore en mode Datastore.