Eliminar datos con una función disponible de Cloud Functions
En esta página se describe cómo usar una función disponible de Cloud Functions para eliminar datos. Una vez que hayas desplegado esta función, podrás llamarla directamente desde tu aplicación móvil o sitio web para eliminar documentos y colecciones de forma recursiva. Por ejemplo, puedes usar esta solución para dar a determinados usuarios la posibilidad de eliminar colecciones enteras.
Para ver otras formas de eliminar colecciones, consulta Eliminar datos.
Solución: eliminar datos con una función disponible de Cloud Functions
Eliminar colecciones enteras de una aplicación móvil con recursos limitados puede ser difícil de implementar por los siguientes motivos:
- No hay ninguna operación que elimine una colección de forma atómica.
- Si eliminas un documento, no se eliminarán los documentos de sus subcolecciones.
- Si tus documentos tienen subcolecciones dinámicas, puede ser difícil saber qué datos eliminar para una ruta determinada.
- Para eliminar una colección de más de 500 documentos, se necesitan varias operaciones de escritura por lotes o cientos de eliminaciones individuales.
- En muchas aplicaciones, no es adecuado dar permiso a los usuarios finales para eliminar colecciones completas.
Por suerte, puedes escribir una función de Cloud invocable para eliminar de forma segura y eficiente colecciones o árboles de colecciones enteros. La función de Cloud Functions que se muestra a continuación implementa una función que se puede invocar, lo que significa que se puede llamar directamente desde tu aplicación móvil o sitio web como si fuera una función local.
Para implementar la función y probar una demostración, consulta el código de ejemplo.
Función de Cloud Functions
La función de Cloud que se muestra a continuación elimina una colección y todos sus elementos descendientes.
En lugar de implementar tu propia lógica de eliminación recursiva para tu función de Cloud, puedes usar el comando firestore:delete
en la interfaz de línea de comandos (CLI) de Firebase. Puedes importar cualquier función de la CLI de Firebase a tu aplicación Node.js mediante el paquete firebase-tools
.
La CLI de Firebase usa la API REST de Firestore para buscar todos los documentos de la ruta especificada y eliminarlos individualmente. Esta implementación no requiere que conozcas la jerarquía de datos específica de tu aplicación. Además, encontrará y eliminará documentos "huérfanos" que ya no tengan un elemento superior.
Node.js
/** * Initiate a recursive delete of documents at a given path. * * The calling user must be authenticated and have the custom "admin" attribute * set to true on the auth token. * * This delete is NOT an atomic operation and it's possible * that it may fail after only deleting some documents. * * @param {string} data.path the document or collection path to delete. */ exports.recursiveDelete = functions .runWith({ timeoutSeconds: 540, memory: '2GB' }) .https.onCall(async (data, context) => { // Only allow admin users to execute this function. if (!(context.auth && context.auth.token && context.auth.token.admin)) { throw new functions.https.HttpsError( 'permission-denied', 'Must be an administrative user to initiate delete.' ); } const path = data.path; console.log( `User ${context.auth.uid} has requested to delete path ${path}` ); // Run a recursive delete on the given document or collection path. // The 'token' must be set in the functions config, and can be generated // at the command line by running 'firebase login:ci'. await firebase_tools.firestore .delete(path, { project: process.env.GCLOUD_PROJECT, recursive: true, force: true, token: functions.config().fb.token }); return { path: path }; });
Invocación de cliente
Para llamar a la función, obtén una referencia a la función del SDK de Firebase y pasa los parámetros necesarios:
Web
/** * Call the 'recursiveDelete' callable function with a path to initiate * a server-side delete. */ function deleteAtPath(path) { var deleteFn = firebase.functions().httpsCallable('recursiveDelete'); deleteFn({ path: path }) .then(function(result) { logMessage('Delete success: ' + JSON.stringify(result)); }) .catch(function(err) { logMessage('Delete failed, see console,'); console.warn(err); }); }
Swift
// Snippet not yet written
Objective‑C
// Snippet not yet written
Kotlin
Android
/** * Call the 'recursiveDelete' callable function with a path to initiate * a server-side delete. */ fun deleteAtPath(path: String) { val deleteFn = Firebase.functions.getHttpsCallable("recursiveDelete") deleteFn.call(hashMapOf("path" to path)) .addOnSuccessListener { // Delete Success // ... } .addOnFailureListener { // Delete Failed // ... } }
Java
Android
/** * Call the 'recursiveDelete' callable function with a path to initiate * a server-side delete. */ public void deleteAtPath(String path) { Map<String, Object> data = new HashMap<>(); data.put("path", path); HttpsCallableReference deleteFn = FirebaseFunctions.getInstance().getHttpsCallable("recursiveDelete"); deleteFn.call(data) .addOnSuccessListener(new OnSuccessListener<HttpsCallableResult>() { @Override public void onSuccess(HttpsCallableResult httpsCallableResult) { // Delete Success // ... } }) .addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // Delete failed // ... } }); }
Al usar el SDK de cliente para funciones de Cloud invocables, el estado de autenticación del usuario y el parámetro path
se transfieren de forma fluida a la función remota.
Cuando la función se complete, el cliente recibirá una devolución de llamada con el resultado o una excepción. Para saber cómo llamar a una función de nube desde Android, Apple u otra plataforma, consulta la documentación.
Limitaciones
La solución que se muestra arriba explica cómo eliminar colecciones de una función a la que se puede llamar, pero debes tener en cuenta las siguientes limitaciones:
- Coherencia: el código anterior elimina los documentos de uno en uno. Si haces una consulta mientras se está llevando a cabo una operación de eliminación, los resultados pueden reflejar un estado parcialmente completado en el que solo se hayan eliminado algunos de los documentos de destino. Tampoco se garantiza que las operaciones de eliminación se completen o fallen de forma uniforme, por lo que debes prepararte para gestionar casos de eliminación parcial.
- Tiempos de espera: la función anterior está configurada para ejecutarse durante un máximo de 540 segundos antes de que se agote el tiempo de espera. El código de eliminación puede eliminar 4000 documentos por segundo en el mejor de los casos. Si necesitas eliminar más de 2.000.000 de documentos, te recomendamos que ejecutes la operación en tu propio servidor para que no se agote el tiempo de espera. Para ver un ejemplo de cómo eliminar una colección de tu propio servidor, consulta Eliminar colecciones.
- Si eliminas un gran número de documentos, puede que el visor de datos de la consola Google Cloud tarde en cargarse o devuelva un error de tiempo de espera.