本頁面說明如何使用可呼叫的 Cloud 函式刪除資料。部署這個函式後,您可以直接從行動應用程式或網站呼叫這個函式,以遞迴方式刪除文件和集合。例如,您可以使用這個解決方案,讓特定使用者刪除整個集合。
如要瞭解刪除集合的其他方法,請參閱「刪除資料」。
解決方案:使用可呼叫的 Cloud 函式刪除資料
難以從資源有限的行動應用程式中刪除整個集合,原因如下:
- 沒有任何作業可原子刪除產品素材資源集合。
- 刪除文件並不會刪除其子集合中的文件。
- 如果文件含有動態子集合,您可能很難判斷要刪除哪些資料。
- 刪除超過 500 份文件的集合需要進行多個批次寫入作業,或數百個單一刪除作業。
- 在許多應用程式中,請勿讓使用者取得刪除整個集合的權限並不適當。
幸好,您可以編寫可呼叫的 Cloud 函式,以安全且執行整個集合或集合樹狀結構刪除作業。下列 Cloud 函式會實作可呼叫函式,這表示您可以像使用本機函式一樣,直接從行動應用程式或網站呼叫該函式。
如要部署函式並試用示範,請參閱程式碼範例。
Cloud 函式
下方的 Cloud 函式會刪除集合及其所有子集。
您可以利用 Firebase 指令列介面 (CLI) 中的 firestore:delete
指令,為 Cloud 函式實作自己的遞迴刪除邏輯。您可以使用 firebase-tools
套件,將 Firebase CLI 的任何函式匯入 Node.js 應用程式。
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); }); }
Swift
// Snippet not yet written
Objective-C
// 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 控制台中資料檢視器的載入速度變慢,或傳回逾時錯誤。