Удаление данных с помощью вызываемой облачной функции

На этой странице описано, как использовать вызываемую облачную функцию для удаления данных. После развертывания этой функции вы можете вызывать ее непосредственно из своего мобильного приложения или веб-сайта для рекурсивного удаления документов и коллекций. Например, вы можете использовать это решение, чтобы предоставить выбранным пользователям возможность удалять целые коллекции.

Другие способы удаления коллекций см. в разделе «Удаление данных» .

Решение: Удаление данных с помощью вызываемой облачной функции.

Удаление целых коллекций из мобильного приложения с ограниченными ресурсами может быть сложной задачей по следующим причинам:

  • Не существует операции, которая бы атомарно удаляла коллекцию.
  • Удаление документа не приводит к удалению документов в его подколлекциях.
  • Если ваши документы содержат динамические подколлекции, может быть сложно определить, какие данные следует удалить для заданного пути.
  • Для удаления коллекции, содержащей более 500 документов, требуется несколько пакетных операций записи или сотни отдельных операций удаления.
  • Во многих приложениях нецелесообразно предоставлять конечным пользователям разрешение на удаление целых коллекций.

К счастью, вы можете написать вызываемую облачную функцию для безопасного и высокопроизводительного удаления целых коллекций или деревьев коллекций. Приведенная ниже облачная функция реализует вызываемую функцию , что означает, что ее можно вызывать непосредственно из вашего мобильного приложения или веб-сайта, как и локальную функцию.

Чтобы развернуть функцию и попробовать демо-версию, см. пример кода .

Облачная функция

Приведенная ниже облачная функция удаляет коллекцию и всех ее потомков.

Вместо того чтобы реализовывать собственную логику рекурсивного удаления для вашей облачной функции, вы можете воспользоваться командой firestore:delete в интерфейсе командной строки Firebase (CLI). Вы можете импортировать любую функцию Firebase CLI в ваше приложение Node.js, используя пакет firebase-tools .

Интерфейс командной строки Firebase использует REST API Cloud Firestore для поиска всех документов по указанному пути и их удаления по отдельности. Эта реализация не требует знания специфической иерархии данных вашего приложения и даже находит и удаляет «осиротевшие» документы, у которых больше нет родительского элемента.

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

Вызов клиента

Для вызова функции получите ссылку на нее из Firebase SDK и передайте необходимые параметры:

Веб
/**
 * 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);
        });
}
Быстрый
Примечание: Этот продукт недоступен для watchOS и приложений App Clip.
    // Snippet not yet written
    
Objective-C
Примечание: Этот продукт недоступен для watchOS и приложений App Clip.
    // Snippet not yet written
    

Kotlin

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

Используя клиентский SDK для вызова облачных функций, состояние аутентификации пользователя и параметр path беспрепятственно передаются в удаленную функцию. После завершения функции клиент получит обратный вызов с результатом или исключением. Чтобы узнать, как вызывать облачные функции с платформ Android, Apple или других платформ, ознакомьтесь с документацией .

Ограничения

Представленное выше решение демонстрирует удаление коллекций из вызываемой функции, однако следует учитывать следующие ограничения:

  • Последовательность — приведенный выше код удаляет документы по одному. Если вы выполните запрос во время выполнения операции удаления, результаты могут отражать частичное завершение процесса, когда удалены только некоторые целевые документы. Также нет гарантии, что операции удаления будут успешными или неудачными одинаково, поэтому будьте готовы к случаям частичного удаления.
  • Тайм-ауты — описанная выше функция настроена на выполнение максимум 540 секунд до истечения тайм-аута. В лучшем случае код удаления может удалять 4000 документов в секунду. Если вам нужно удалить более 2 000 000 документов, следует рассмотреть возможность выполнения операции на собственном сервере, чтобы избежать тайм-аута. Пример удаления коллекции с собственного сервера см. в разделе «Удаление коллекций» .
  • Удаление большого количества документов может привести к медленной загрузке средства просмотра данных в консоли Google Cloud или к ошибке тайм-аута.