Supprimer des données avec une Callable Cloud Function

La page décrit comment utiliser une fonction Cloud appelable pour supprimer des données. Une fois que vous avez déployé cette fonction, vous pouvez l'appeler directement depuis votre application mobile ou votre site Web pour supprimer de manière récursive des documents et des collections. Par exemple, vous pouvez utiliser cette solution pour donner à certains utilisateurs la possibilité de supprimer des collections entières.

Pour d'autres façons de supprimer des collections, voir Supprimer des données .

Solution : supprimer des données avec une fonction cloud appelable

La suppression de collections entières d'une application mobile aux ressources limitées peut être difficile à mettre en œuvre pour les raisons suivantes :

  • Il n'y a pas d'opération qui supprime atomiquement une collection.
  • La suppression d'un document ne supprime pas les documents de ses sous-collections.
  • Si vos documents ont des sous-collections dynamiques, il peut être difficile de savoir quelles données supprimer pour un chemin donné.
  • La suppression d'une collection de plus de 500 documents nécessite plusieurs opérations d'écriture par lots ou des centaines de suppressions uniques.
  • Dans de nombreuses applications, il n'est pas approprié d'autoriser les utilisateurs finaux à supprimer des collections entières.

Heureusement, vous pouvez écrire une fonction cloud appelable pour exécuter des suppressions sûres et performantes de collections entières ou d'arborescences de collections. La fonction Cloud ci-dessous implémente une fonction appelable, ce qui signifie qu'elle peut être appelée directement depuis votre application mobile ou votre site Web, comme vous le feriez pour une fonction locale.

Pour déployer la fonction et essayer une démo, consultez l' exemple de code .

Fonction cloud

La fonction Cloud ci-dessous supprime une collection et tous ses descendants.

Au lieu d'implémenter votre propre logique de suppression récursive pour votre fonction Cloud, vous pouvez tirer parti de la commande firestore:delete dans l'interface de ligne de commande Firebase (CLI). Vous pouvez importer n'importe quelle fonction de la CLI Firebase dans votre application Node.js à l'aide du firebase-tools .

La CLI Firebase utilise l'API REST Cloud Firestore pour rechercher tous les documents sous le chemin spécifié et les supprimer individuellement. Cette implémentation ne nécessite aucune connaissance de la hiérarchie des données spécifiques de votre application et trouvera et supprimera même les documents "orphelins" qui n'ont plus de parent.

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

Invocation du client

Pour appeler la fonction, obtenez une référence à la fonction à partir du SDK Firebase et transmettez les paramètres requis :

la toile
/**
 * 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);
        });
}
Rapide
Remarque : ce produit n'est pas disponible sur les cibles watchOS et App Clip.
    // Snippet not yet written
    
Objectif c
Remarque : ce produit n'est pas disponible sur les cibles watchOS et App Clip.
    // Snippet not yet written
    

Java

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

Kotlin+KTX

/**
 * 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
                // ...
            }
}

En utilisant le SDK client pour les fonctions cloud appelables, l'état d'authentification des utilisateurs et le paramètre de path sont transmis de manière transparente à la fonction distante. Une fois la fonction terminée, le client recevra un rappel avec le résultat ou une exception. Pour savoir comment appeler une fonction cloud depuis Android, Apple ou une autre plate-forme, lisez la documentation .

Limites

La solution présentée ci-dessus illustre la suppression de collections d'une fonction appelable, mais vous devez être conscient des limitations suivantes :

  • Cohérence - le code ci-dessus supprime les documents un par un. Si vous effectuez une requête alors qu'une opération de suppression est en cours, vos résultats peuvent refléter un état partiellement terminé dans lequel seuls certains documents ciblés sont supprimés. Il n'y a pas non plus de garantie que les opérations de suppression réussiront ou échoueront de manière uniforme, soyez donc prêt à gérer les cas de suppression partielle.
  • Délais d'attente - la fonction ci-dessus est configurée pour s'exécuter pendant un maximum de 540 secondes avant l'expiration du délai. Le code de suppression peut supprimer 4000 documents par seconde dans le meilleur des cas. Si vous devez supprimer plus de 2 000 000 de documents, vous devez envisager d'exécuter l'opération sur votre propre serveur afin qu'elle n'expire pas. Pour un exemple de suppression d'une collection de votre propre serveur, voir Supprimer des collections .