Daten mit einer aufrufbaren Cloud Functions-Funktion löschen

Auf dieser Seite wird beschrieben, wie Sie eine aufrufbare Cloud Functions-Funktion zum Löschen von Daten verwenden. Nach der Bereitstellung dieser Funktion können Sie sie direkt über Ihre mobile App oder Website aufrufen, um Dokumente und Sammlungen rekursiv zu löschen. Sie können diese Lösung beispielsweise verwenden, um ausgewählten Nutzern die Möglichkeit zu geben, ganze Sammlungen zu löschen.

Weitere Möglichkeiten zum Löschen von Sammlungen finden Sie unter Daten löschen.

Lösung: Daten mit einer aufrufbaren Cloud Functions-Funktion löschen

Das Löschen vollständiger Sammlungen aus einer ressourcenbeschränkten mobilen App kann aus folgenden Gründen schwierig sein:

  • Es gibt keinen Vorgang, der eine Sammlung automatisch löscht.
  • Wenn Sie ein Dokument löschen, werden die Dokumente in den untergeordneten Sammlungen nicht gelöscht.
  • Wenn Ihre Dokumente dynamische untergeordnete Sammlungen haben, können Sie möglicherweise nur schwer ermitteln, welche Daten für einen bestimmten Pfad gelöscht werden sollen.
  • Wenn Sie eine Sammlung mit mehr als 500 Dokumenten löschen, sind mehrere Schreibvorgänge oder Hunderte einzelner Löschvorgänge erforderlich.
  • In vielen Anwendungen ist es nicht angebracht, Endnutzern die Berechtigung zum Löschen ganzer Sammlungen zu erteilen.

Sie können aber eine aufrufbare Cloud Functions-Funktion schreiben, um sichere und leistungsfähige Löschvorgänge für ganze Sammlungen oder Sammlungsbäume auszuführen. Die folgende Cloud-Funktion implementiert eine aufrufbare Funktion, die wie eine lokale Funktion direkt von Ihrer mobilen App oder Website aus aufgerufen werden kann.

Informationen zum Bereitstellen der Funktion und zum Testen einer Demo finden Sie im Beispielcode.

Cloud Functions-Funktion

Mit der folgenden Cloud Functions-Funktion wird eine Sammlung mit allen untergeordneten Elementen gelöscht.

Statt Ihre eigene rekursive Löschlogik für Ihre Cloud Functions-Funktion zu implementieren, können Sie den firestore:delete-Befehl in Firebase Command Line Interface (Firebase CLI) nutzen. Sie können jede Funktion von Firebase CLI mithilfe des Pakets firebase-tools in Ihre Node.js-Anwendung importieren.

Firebase CLI verwendet die Firestore REST API, um alle Dokumente unter dem angegebenen Pfad zu finden und einzeln zu löschen. Diese Implementierung erfordert keine Kenntnis der spezifischen Datenhierarchie Ihrer Anwendung. Sie findet und löscht auch verwaiste Dokumente, die keine übergeordneten Elementen mehr haben.

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,
        yes: true,
        token: functions.config().fb.token
      });

    return {
      path: path
    };
  });

Client-Aufruf

Zum Aufrufen der Funktion rufen Sie im Firebase SDK einen Verweis zur Funktion ab und übergeben die erforderlichen Parameter:

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

Durch Verwendung des Client SDK für aufrufbare Cloud Functions-Funktionen werden der Authentifizierungsstatus der Nutzer und der Parameter path nahtlos an die Remote-Funktion übergeben. Wenn die Funktion abgeschlossen ist, erhält der Client einen Rückruf mit dem Ergebnis oder einer Ausnahme. Informationen zum Aufrufen einer Cloud Functions-Funktion über Android, iOS oder eine andere Plattform erhalten Sie in der Dokumentation.

Beschränkungen

In der oben gezeigten Lösung wird das Löschen von Sammlungen aus einer aufrufbaren Funktion dargestellt. Beachten Sie jedoch die folgenden Beschränkungen:

  • Konsistenz: Mit dem obigen Code werden Dokumente einzeln gelöscht. Wenn Sie während eines laufenden Löschvorgangs eine Abfrage durchführen, werden in den Ergebnissen möglicherweise unvollständige Zustände angezeigt, in denen nur bestimmte Dokumente gelöscht sind. Es gibt auch keine Garantie dafür, dass die Löschvorgänge einheitlich erfolgreich ausgeführt werden oder fehlschlagen. Daher sollten Sie in der Lage sein, auch mit unvollständigen Löschvorgängen umzugehen.
  • Zeitüberschreitungen: Die obige Funktion ist so konfiguriert, dass sie bis zu 540 Sekunden ausgeführt wird, bevor eine Zeitüberschreitung auftritt. Der Löschcode kann im besten Fall 4.000 Dokumente pro Sekunde löschen. Wenn Sie mehr als 2.000.000 Dokumente löschen müssen, sollten Sie den Vorgang auf Ihrem eigenen Server ausführen, damit keine Zeitüberschreitung stattfindet. Ein Beispiel zum Löschen einer Sammlung von Ihrem eigenen Server finden Sie unter Sammlungen löschen.