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

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

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

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

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

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

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

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

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

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

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

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

Ограничения

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

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