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