Elimine dados com uma função do Cloud Function chamável
A página descreve como usar uma Cloud Function chamável para eliminar dados. Depois de implementar esta função, pode chamá-la diretamente a partir da sua app para dispositivos móveis ou Website para eliminar documentos e coleções recursivamente. Por exemplo, pode usar esta solução para dar a utilizadores selecionados a capacidade de eliminar coleções inteiras.
Para outras formas de eliminar coleções, consulte o artigo Elimine dados.
Solução: elimine dados com uma função do Google Cloud invocável
A eliminação de coleções inteiras de uma app para dispositivos móveis com recursos limitados pode ser difícil de implementar pelos seguintes motivos:
- Não existe nenhuma operação que elimine atomicamente uma coleção.
- A eliminação de um documento não elimina os documentos nas respetivas subcoleções.
- Se os seus documentos tiverem subcoleções dinâmicas, pode ser difícil saber que dados eliminar para um determinado caminho.
- A eliminação de uma coleção de mais de 500 documentos requer várias operações de escrita em lote ou centenas de eliminações únicas.
- Em muitas apps, não é adequado conceder aos utilizadores finais autorização para eliminar coleções inteiras.
Felizmente, pode escrever uma função do Google Cloud chamável para executar eliminações seguras e com bom desempenho de coleções inteiras ou árvores de coleções. A função da nuvem abaixo implementa uma função chamável, o que significa que pode ser chamada diretamente a partir da sua app para dispositivos móveis ou Website, tal como faria para uma função local.
Para implementar a função e experimentar uma demonstração, consulte o código de exemplo.
Função do Cloud
A função do Google Cloud abaixo elimina uma coleção e todos os respetivos descendentes.
Em vez de implementar a sua própria lógica de eliminação recursiva para a sua função do Cloud, pode tirar partido do comando firestore:delete
na interface de linhas de comando (CLI) do Firebase. Pode importar qualquer função da
Firebase CLI para a sua aplicação Node.js através do pacote firebase-tools
.
A Firebase CLI usa a API REST do Firestore para encontrar todos os documentos no caminho especificado e eliminá-los individualmente. Esta implementação não requer conhecimentos sobre a hierarquia de dados específica da sua app e até encontra e elimina documentos "órfãos" que já não têm um elemento principal.
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 }; });
Invocação do cliente
Para chamar a função, obtenha uma referência à função a partir do SDK do Firebase e transmita os parâmetros necessários:
Web
/** * 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
Android
/** * 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
Android
/** * 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 // ... } }); }
Ao usar o SDK do cliente para funções da nuvem chamáveis, o estado de autenticação do utilizador e o parâmetro path
são transmitidos de forma integrada para a função remota.
Quando a função é concluída, o cliente recebe uma chamada de retorno com o resultado ou uma exceção. Para saber como chamar uma função na nuvem a partir do Android, da Apple ou de outra plataforma, leia a documentação.
Limitações
A solução apresentada acima demonstra a eliminação de coleções de uma função invocável, mas deve ter em atenção as seguintes limitações:
- Consistência: o código acima elimina os documentos um de cada vez. Se fizer uma consulta enquanto existir uma operação de eliminação em curso, os resultados podem refletir um estado parcialmente concluído em que apenas alguns documentos segmentados são eliminados. Também não existe garantia de que as operações de eliminação sejam bem-sucedidas ou falhem uniformemente, por isso, prepare-se para processar casos de eliminação parcial.
- Tempos limite: a função acima está configurada para ser executada durante um máximo de 540 segundos antes de exceder o tempo limite. O código de eliminação pode eliminar 4000 documentos por segundo no melhor caso. Se precisar de eliminar mais de 2 000 000 de documentos, deve considerar executar a operação no seu próprio servidor para que não expire. Para ver um exemplo de como eliminar uma coleção do seu próprio servidor, consulte o artigo Elimine coleções.
- A eliminação de um grande número de documentos pode fazer com que o visualizador de dados na consola Google Cloud seja carregado lentamente ou devolva um erro de limite de tempo.