หน้านี้จะอธิบายวิธีใช้ Cloud Function ที่เรียกใช้ได้เพื่อลบข้อมูล เมื่อติดตั้งใช้งานฟังก์ชันนี้แล้ว คุณสามารถเรียกใช้ฟังก์ชันดังกล่าวจากแอปบนอุปกรณ์เคลื่อนที่หรือเว็บไซต์โดยตรงเพื่อลบเอกสารและคอลเล็กชันแบบซ้ำ เช่น คุณสามารถใช้โซลูชันนี้เพื่อให้ผู้ใช้บางรายลบคอลเล็กชันทั้งคอลเล็กชันได้
โปรดดูวิธีอื่นๆ ในการลบคอลเล็กชันที่หัวข้อลบข้อมูล
วิธีแก้ไข: ลบข้อมูลด้วย Cloud Function ที่เรียกใช้ได้
การลบคอลเล็กชันทั้งหมดออกจากแอปบนอุปกรณ์เคลื่อนที่ซึ่งมีทรัพยากรจำกัดอาจใช้งานได้ยากเนื่องจากเหตุผลดังต่อไปนี้
- ไม่มีการดำเนินการที่ลบคอลเล็กชันอย่างสมบูรณ์
- การลบเอกสารไม่ได้เป็นการลบเอกสารในคอลเล็กชันย่อยของเอกสารนั้น
- หากเอกสารมีคอลเล็กชันย่อยแบบไดนามิก การจะดูข้อมูลใดในเส้นทางหนึ่งๆ อาจเป็นเรื่องยาก
- การลบคอลเล็กชันเอกสารมากกว่า 500 รายการต้องใช้การดำเนินการเขียนแบบเป็นกลุ่มหลายรายการหรือการลบรายการเดียวหลายร้อยรายการ
- ในหลายแอป การให้สิทธิ์ผู้ใช้ปลายทางลบคอลเล็กชันทั้งหมดนั้นไม่เหมาะสม
แต่คุณเขียน Cloud Function ที่เรียกใช้ได้เพื่อดำเนินการลบทั้งคอลเล็กชันหรือทั้งลําดับชั้นคอลเล็กชันได้อย่างปลอดภัยและมีประสิทธิภาพ Cloud Function ด้านล่างใช้ฟังก์ชันที่เรียกใช้ได้ ซึ่งหมายความว่าสามารถเรียกใช้จากแอปบนอุปกรณ์เคลื่อนที่หรือเว็บไซต์ได้โดยตรงเช่นเดียวกับฟังก์ชันในเครื่อง
หากต้องการทําให้ฟังก์ชันใช้งานได้และลองใช้เดโม โปรดดูโค้ดตัวอย่าง
Cloud Function
ฟังก์ชัน Cloud ด้านล่างจะลบคอลเล็กชันและรายการที่สืบทอดทั้งหมด
คุณใช้ประโยชน์จากคำสั่ง firestore:delete
ในอินเทอร์เฟซบรรทัดคำสั่ง (CLI) ของ Firebase ได้แทนการใช้ตรรกะการลบแบบซ้ำซ้อนของคุณเองสำหรับ Cloud Function คุณนำเข้าฟังก์ชันใดก็ได้ของ Firebase CLI ไปยังแอปพลิเคชัน Node.js โดยใช้แพ็กเกจ firebase-tools
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 ของไคลเอ็นต์สำหรับฟังก์ชัน Cloud ที่เรียกใช้ได้ ระบบจะส่งสถานะการตรวจสอบสิทธิ์ของผู้ใช้และพารามิเตอร์ path
ไปยังฟังก์ชันระยะไกลอย่างราบรื่น
เมื่อฟังก์ชันเสร็จสมบูรณ์ ไคลเอ็นต์จะได้รับการติดต่อกลับพร้อมผลลัพธ์หรือข้อยกเว้น หากต้องการดูข้อมูลเกี่ยวกับวิธีเรียกใช้ฟังก์ชันระบบคลาวด์จาก Android, Apple หรือแพลตฟอร์มอื่นๆ โปรดอ่านเอกสารประกอบ
ข้อจำกัด
โซลูชันที่แสดงด้านบนแสดงการลบคอลเล็กชันจากฟังก์ชันที่เรียกใช้ได้ แต่คุณควรทราบข้อจํากัดต่อไปนี้
- ความสอดคล้อง - โค้ดด้านบนจะลบเอกสารทีละรายการ หากคุณค้นหาขณะดำเนินการลบที่ดำเนินอยู่ ผลการค้นหาอาจแสดงสถานะที่สมบูรณ์บางส่วน ซึ่งมีการลบเอกสารเป้าหมายบางรายการเท่านั้น นอกจากนี้ เรายังไม่รับประกันว่าการดำเนินการลบจะสำเร็จหรือล้มเหลวอย่างสม่ำเสมอ ดังนั้นโปรดเตรียมพร้อมรับมือกับกรณีที่มีการลบเพียงบางส่วน
- การหมดเวลา - ฟังก์ชันด้านบนได้รับการกําหนดค่าให้ทํางานสูงสุด 540 วินาทีก่อนที่จะหมดเวลา รหัสการลบสามารถลบเอกสารได้ 4,000 รายการต่อวินาทีในกรณีที่ดีที่สุด หากต้องการลบเอกสารมากกว่า 2,000,000 รายการ คุณควรพิจารณาเรียกใช้การดำเนินการในเซิร์ฟเวอร์ของคุณเองเพื่อไม่ให้หมดเวลา ดูตัวอย่างวิธีลบคอลเล็กชันจากเซิร์ฟเวอร์ของคุณเองได้ที่ลบคอลเล็กชัน
- การลบเอกสารจํานวนมากอาจทําให้เครื่องมือดูข้อมูลในคอนโซล Google Cloud โหลดช้าหรือแสดงข้อผิดพลาดเกี่ยวกับเวลาหมด