На этой странице описано, как использовать вызываемую функцию Cloud Functions для удаления данных. После развертывания этой функции вы можете вызывать ее непосредственно из своего мобильного приложения или веб-сайта для рекурсивного удаления документов и коллекций. Например, вы можете использовать это решение, чтобы предоставить определенным пользователям возможность удалять целые коллекции.
Другие способы удаления коллекций описаны в статье Удаление данных.
Решение: удаление данных с помощью вызываемой функции Cloud Functions
Удаление целых коллекций из мобильного приложения с ограниченными ресурсами может быть затруднено по следующим причинам:
- Операции, которая бы удаляла коллекцию атомарно, не существует.
- При удалении документа документы в его подколлекциях не удаляются.
- Если в ваших документах есть динамические подколлекции, может быть сложно определить, какие данные следует удалить для данного пути.
- Для удаления коллекции, содержащей более 500 документов, требуется несколько пакетных операций записи или сотни отдельных удалений.
- Во многих приложениях нецелесообразно предоставлять конечным пользователям разрешение на удаление целых коллекций.
К счастью, вы можете написать вызываемую функцию Cloud Functions, чтобы безопасно и эффективно удалять целые коллекции или деревья коллекций. Функция Cloud Functions, приведенная ниже, реализует вызываемую функцию. Это означает, что ее можно вызвать непосредственно из мобильного приложения или с сайта, как и локальную функцию.
Чтобы развернуть функцию и попробовать демоверсию, ознакомьтесь с примером кода.
Cloud Functions
Функция Cloud Functions, приведенная ниже, удаляет коллекцию и все ее дочерние элементы.
Вместо того чтобы реализовывать собственную логику рекурсивного удаления для функции Cloud Functions, вы можете воспользоваться командой firestore:delete в интерфейсе командной строки 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); }); }
Swift
// Snippet not yet written
Objective-C
// 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 для вызываемых функций Cloud Functions статус аутентификации пользователя и параметр path без проблем передаются удаленной функции.
Когда функция завершит работу, клиент получит обратный вызов с результатом или исключением. О том, как вызвать облачную функцию из Android, Apple или другой платформы, читайте в документации.
Ограничения
Решение, показанное выше, демонстрирует удаление коллекций из вызываемой функции, но вы должны знать о следующих ограничениях:
- Согласованность. Приведенный выше код удаляет документы по одному. Если вы выполните запрос во время операции удаления, результаты могут отражать частично завершенное состояние, когда удалены только некоторые целевые документы. Также нет гарантии, что операции удаления будут выполнены успешно или завершатся сбоем. Будьте готовы к тому, что удаление может быть выполнено частично.
- Тайм-ауты. Функция выше настроена на выполнение в течение максимум 540 секунд до тайм-аута. Код удаления может удалять 4000 документов в секунду в лучшем случае. Если вам нужно удалить более 2 000 000 документов, рекомендуем выполнить эту операцию на собственном сервере, чтобы избежать превышения времени ожидания. Пример удаления коллекции с собственного сервера приведен в разделе Удаление коллекций.
- Удаление большого количества документов может привести к медленной загрузке средства просмотра данных в виде таблицы в консоли Google Cloud или к ошибке тайм-аута.