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

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

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

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

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

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

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

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

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

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

Вместо реализации собственной логики рекурсивного удаления для облачной функции вы можете воспользоваться командой firestore:delete в интерфейсе командной строки (CLI) Firebase. Вы можете импортировать любую функцию интерфейса командной строки Firebase в свое приложение 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
    
Цель-C
Примечание. Этот продукт недоступен для целей watchOS и 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
                // ...
            }
}

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

Ограничения

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

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