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

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

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

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

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

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

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

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

Функция облака

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

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

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

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 или возникновению ошибки тайм-аута.