Elimina i dati con una Callable Cloud Function

La pagina descrive come utilizzare una Cloud Function richiamabile per eliminare i dati. Una volta distribuita questa funzione, puoi richiamarla direttamente dalla tua app mobile o dal tuo sito web per eliminare in modo ricorsivo documenti e raccolte. Ad esempio, puoi utilizzare questa soluzione per offrire a utenti selezionati la possibilità di eliminare intere raccolte.

Per altri modi per eliminare le raccolte, consulta Eliminare dati .

Soluzione: eliminare i dati con una Cloud Function richiamabile

L'eliminazione di intere raccolte da un'app mobile con risorse limitate può essere difficile da implementare per i seguenti motivi:

  • Non esiste alcuna operazione che elimini atomicamente una raccolta.
  • L'eliminazione di un documento non elimina i documenti nelle sue sottoraccolte.
  • Se i tuoi documenti hanno sottoraccolte dinamiche, può essere difficile sapere quali dati eliminare per un determinato percorso.
  • L'eliminazione di una raccolta di oltre 500 documenti richiede più operazioni di scrittura in batch o centinaia di singole eliminazioni.
  • In molte app non è appropriato concedere agli utenti finali l'autorizzazione a eliminare intere raccolte.

Fortunatamente, puoi scrivere una Cloud Function richiamabile per eseguire eliminazioni sicure ed efficienti di intere raccolte o alberi di raccolte. La funzione cloud di seguito implementa una funzione richiamabile , ovvero può essere richiamata direttamente dall'app mobile o dal sito Web come faresti per una funzione locale.

Per distribuire la funzione e provare una demo, vedere il codice di esempio .

Funzione nuvola

La funzione Cloud di seguito elimina una raccolta e tutti i relativi discendenti.

Invece di implementare la tua logica di eliminazione ricorsiva per la tua Cloud Function, puoi sfruttare il comando firestore:delete nell'interfaccia a riga di comando (CLI) di Firebase. Puoi importare qualsiasi funzione della CLI Firebase nella tua applicazione Node.js utilizzando il pacchetto firebase-tools .

La CLI Firebase utilizza l'API REST di Cloud Firestore per trovare tutti i documenti nel percorso specificato ed eliminarli singolarmente. Questa implementazione non richiede la conoscenza della gerarchia dei dati specifica della tua app e troverà ed eliminerà anche i documenti "orfani" che non hanno più un genitore.

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

Invocazione del cliente

Per chiamare la funzione, ottieni un riferimento alla funzione dall'SDK Firebase e passa i parametri richiesti:

ragnatela
/**
 * 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);
        });
}
Veloce
Nota: questo prodotto non è disponibile sui target watchOS e App Clip.
    // Snippet not yet written
    
Obiettivo-C
Nota: questo prodotto non è disponibile sui target watchOS e App Clip.
    // Snippet not yet written
    

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

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

Utilizzando l'SDK client per le funzioni cloud richiamabili, lo stato di autenticazione degli utenti e il parametro path vengono passati senza problemi alla funzione remota. Al termine della funzione, il client riceverà una richiamata con il risultato o un'eccezione. Per sapere come richiamare una funzione cloud da Android, Apple o un'altra piattaforma, leggi la documentazione .

Limitazioni

La soluzione mostrata sopra dimostra l'eliminazione di raccolte da una funzione richiamabile, ma è necessario tenere presente le seguenti limitazioni:

  • Coerenza : il codice sopra elimina i documenti uno alla volta. Se esegui una query mentre è in corso un'operazione di eliminazione, i risultati potrebbero riflettere uno stato parzialmente completo in cui vengono eliminati solo alcuni documenti mirati. Inoltre, non vi è alcuna garanzia che le operazioni di eliminazione abbiano successo o falliscano in modo uniforme, quindi preparati a gestire casi di eliminazione parziale.
  • Timeout : la funzione sopra è configurata per essere eseguita per un massimo di 540 secondi prima del timeout. Nel migliore dei casi il codice di cancellazione può cancellare 4000 documenti al secondo. Se devi eliminare più di 2.000.000 di documenti, dovresti considerare di eseguire l'operazione sul tuo server in modo che non vada in timeout. Per un esempio di come eliminare una raccolta dal tuo server, consulta Eliminare raccolte .