Activadores de Cloud Firestore

Con Cloud Functions, puedes controlar eventos en Cloud Firestore sin necesidad de actualizar el código del cliente. Puedes hacer cambios en Cloud Firestore a través de la interfaz DeltaDocumentSnapshot o mediante el SDK de Admin.

En un ciclo de vida típico, una función Cloud Firestore hace lo siguiente:

  1. Espera a que ocurran cambios en un documento en particular.
  2. Se activa cuando ocurre un evento y realiza sus tareas (consulta ¿Qué puedo hacer con Cloud Functions? para ver ejemplos de casos prácticos).
  3. Recibe un objeto de datos de evento que contiene dos instantáneas de los datos almacenados en el documento especificado: una con los datos originales previos al cambio y una con los datos nuevos.

Activa una función de Cloud Firestore

Las funciones del SDK de Cloud Functions para Firebase exportan un objeto functions.firestore que te permite crear controladores vinculados con eventos específicos.

Cloud Firestore admite los eventos create, update, delete y write:

Tipo de evento Activador
onCreate Se activa cuando se escribe en un documento por primera vez.
onUpdate Se activa cuando un documento ya existe y se cambia uno de sus valores.
onDelete Se activa cuando se borra un documento con datos.
onWrite Se activa cuando se activa onCreate, onUpdate u onDelete.

Si aún no tienes un proyecto habilitado para Cloud Functions para Firebase, lee Primeros pasos: Cómo escribir e implementar tus primeras funciones para configurar el proyecto de Cloud Functions para Firebase.

Activa una función cuando un documento específico cambia

Si deseas activar un evento para cualquier cambio en un documento específico, puedes usar la siguiente función.

Node.js

// Listen for any change on document `marie` in collection `users`
exports.myFunctionName = functions.firestore
    .document('users/marie').onWrite((event) => {
        // ... Your code here
    });

Activa una función cuando se crea un documento nuevo

Puedes hacer que se active una función cada vez que se cree un documento nuevo en una colección mediante un controlador onCreate() con un comodín. Esta función de ejemplo llama a createUser cada vez que se agrega un perfil de usuario nuevo:

Node.js

exports.createUser = functions.firestore
    .document('users/{userId}')
    .onCreate(event => {
        // Get an object representing the document
        // e.g. {'name': 'Marie', 'age': 66}
        const newValue = event.data.data();

        // access a particular field as you would any JS property
        const name = newValue.name;

        // perform desired operations ...
    });

Activa una función cuando se actualiza un documento

También puedes hacer que se active una función cuando se actualice un documento mediante la función onUpdate() con un comodín. Esta función de ejemplo llama a updateUser cada vez que un usuario cambia su perfil:

Node.js

exports.updateUser = functions.firestore
    .document('users/{userId}')
    .onUpdate(event => {
        // Get an object representing the document
        // e.g. {'name': 'Marie', 'age': 66}
        const newValue = event.data.data();

        // ...or the previous value before this update
        const previousValue = event.data.previous.data();

        // access a particular field as you would any JS property
        const name = newValue.name;

        // perform desired operations ...
    });

Activa una función cuando se borra un documento

También puedes activar una función cuando se borre un documento mediante la función onDelete() con un comodín. Esta función de ejemplo llama a deleteUser cuando un usuario borra su perfil:

Node.js

exports.deleteUser = functions.firestore
    .document('users/{userID}')
    .onDelete(event => {
        // Get an object representing the document prior to deletion
        // e.g. {'name': 'Marie', 'age': 66}
        const deletedValue = event.data.previous.data();

        // perform desired operations ...
    });

Activa una función para cualquier cambio en un documento

Si no te importa el tipo de evento que se activa, puedes escuchar para detectar todos los cambios en un documento de Cloud Firestore mediante la función onWrite() con un comodín. Esta función de ejemplo llama a modifyUser si se crea, se actualiza o se borra un usuario:

Node.js

exports.modifyUser = functions.firestore
    .document('users/{userID}')
    .onWrite(event => {
        // Get an object with the current document value.
        // If the document does not exist, it has been deleted.
        const document = event.data.exists ? event.data.data() : null;

        // Get an object with the previous document value (for update or delete)
        const oldDocument = event.data.previous.data();

        // perform desired operations ...
    });

Controla datos de eventos

Lectura de datos

Cuando se activa una función, es posible que desees obtener datos de un documento que se actualizó o que quieras obtener los datos antes de la actualización. Para obtener estos datos, puedes usar event.data, que contiene el documento actual (event.data.data()) y el documento anterior a la actualización (event.data.previous.data()).

Node.js

exports.updateUser = functions.firestore
    .document('users/{userId}')
    .onUpdate(event => {
        // Get an object representing the current document
        const newValue = event.data.data();

        // ...or the previous value before this update
        const previousValue = event.data.previous.data();
    });

Puedes acceder a las propiedades del mismo modo que con cualquier otro objeto. También puedes utilizar la función get para acceder a campos específicos:

Node.js

// Fetch data using standard accessors
const age = event.data.data().age;
const name = event.data.data()['name'];

// Fetch data using built in accessor
const experience = event.data.get('experience');

Escritura de datos

Cada invocación de función está asociada a un documento específico en tu base de datos de Cloud Firestore. Puedes acceder a ese documento como una DocumentReference en event.data.ref.

Esta DocumentReference proviene del SDK de Node.js de Cloud Firestore; incluye métodos como update(), set() y remove() para que puedas modificar fácilmente el documento que activó la función.

Node.js

// Listen for updates to any `user` document.
exports.countNameChanges = functions.firestore
    .document('users/{userId}')
    .onUpdate((event) => {
        // Retrieve the current and previous value
        const data = event.data.data();
        const previousData = event.data.previous.data();

        // We'll only update if the name has changed.
        // This is crucial to prevent infinite loops.
        if (data.name == previousData.name) return;

        // 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 event.data.ref.set({
            name_change_count: count + 1
        }, {merge: true});
    });

Uso de comodines y parámetros

Si no conoces el documento específico al que deseas adjuntar un activador de evento, puedes usar un {wildcard} en lugar del ID del documento.

Node.js

// Listen for changes in all documents and all sub-collections
exports.useWildcard = functions.firestore
    .document('users/{userId}')
    .onWrite((event) => {
        // If we set `/users/marie` to {name: "marie"} then
        // event.params.userId == "marie"
        // ... and ...
        // event.data.data() == {name: "Marie"}
    });

En este ejemplo, cuando se cambia algún campo en cualquier documento de users, coincide con un comodín denominado userId.

Si un documento de users tiene subcolecciones y se cambia un campo en uno de los documentos de esas subcolecciones, el comodín userId no se activa.

Las coincidencias de comodines se extraen de la ruta del documento y se almacenan en event.params. Puedes definir tantos comodines como desees para sustituir los ID explícitos de colección o de documento.

Node.js

// Listen for changes in all documents and all subcollections
exports.useMultipleWildcards = functions.firestore
    .document('users/{userId}/{messageCollectionId}/{messageId}')
    .onWrite((event) => {
        // If we set `/users/marie/incoming_messages/134` to {body: "Hello"} then
        // event.params.userId == "malcolm";
        // event.params.messageCollectionId == "incoming_messages";
        // event.params.messageId == "134";
        // ... and ...
        // event.data.data() == {body: "Hello"}
    });

Limitaciones y garantías

Mientras programas tus aplicaciones, ten en cuenta que tanto Cloud Firestore como Cloud Functions para Firebase están actualmente en versión Beta, lo que puede generar un comportamiento inesperado.

Estas son algunas limitaciones conocidas:

  • Puede tardar más de 5 segundos en que se active una función después de un cambio en los datos de Cloud Firestore.
  • La entrega de invocaciones de funciones no está garantizada actualmente. A medida que mejore la integración de Cloud Firestore y Cloud Functions, pensamos garantizar la entrega "al menos una vez". Sin embargo, es posible que esto no ocurra siempre en la versión Beta. Esto también puede generar varias invocaciones para un solo evento, por lo que debes asegurarte de que las funciones de mayor calidad se escriban para ser idempotentes.
  • El ordenamiento no está garantizado. Es posible que los cambios rápidos activen invocaciones de funciones en un orden inesperado.

Enviar comentarios sobre…

¿Necesitas ayuda? Visita nuestra página de asistencia.