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