حذف البيانات باستخدام دالة السحابة الإلكترونية القابلة للاستدعاء
تنظيم صفحاتك في مجموعات
يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.
توضّح الصفحة كيفية استخدام دالة Cloud قابلة للاستدعاء لحذف البيانات. بعد نشر هذه الدالة، يمكنك استدعاؤها مباشرةً من تطبيقك على الأجهزة الجوّالة أو موقعك الإلكتروني لحذف المستندات والمجموعات بشكل متكرّر. على سبيل المثال، يمكنك استخدام هذا الحلّ لمنح مستخدمين محدّدين إمكانية حذف مجموعات كاملة.
للاطّلاع على طرق أخرى لحذف المجموعات، يُرجى الانتقال إلى حذف البيانات.
الحلّ: حذف البيانات باستخدام Cloud Function قابلة للاستدعاء
قد يكون من الصعب حذف مجموعات كاملة من تطبيق للأجهزة الجوّالة ذي موارد محدودة للأسباب التالية:
لا تتوفّر عملية تحذف مجموعة بشكل متزامن.
لا يؤدي حذف مستند إلى حذف المستندات في مجموعاته الفرعية.
إذا كانت مستنداتك تتضمّن مجموعات فرعية ديناميكية، قد يصعب معرفة البيانات التي يجب حذفها لمسار معيّن.
يتطلّب حذف مجموعة تضم أكثر من 500 مستند إجراء عمليات كتابة مجمّعة متعددة أو مئات عمليات الحذف الفردية.
في العديد من التطبيقات، لا يكون من المناسب منح المستخدمين النهائيين الإذن بحذف مجموعات كاملة.
لحسن الحظ، يمكنك كتابة دالة Cloud قابلة للاستدعاء
لتنفيذ عمليات حذف آمنة وفعّالة لمجموعات أو أشجار مجموعات بأكملها. تنفّذ Cloud Function أدناه دالة قابلة للاستدعاء،
ما يعني أنّه يمكن استدعاؤها مباشرةً من تطبيقك على الأجهزة الجوّالة أو موقعك الإلكتروني كما تفعل مع دالة محلية.
لنشر الدالة وتجربة عرض توضيحي، اطّلِع على الرمز النموذجي.
وظيفة السحابة الإلكترونية
تحذف Cloud Function أدناه مجموعة وجميع العناصر التابعة لها.
بدلاً من تنفيذ منطق الحذف المتكرّر الخاص بك في Cloud Functions، يمكنك الاستفادة من الأمر firestore:delete في واجهة سطر الأوامر (CLI) الخاصة بـ Firebase. يمكنك استيراد أي دالة من
Firebase CLI إلى تطبيق Node.js باستخدام حزمة firebase-tools.
تستخدم واجهة سطر الأوامر (CLI) في Firebase واجهة 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)){thrownewfunctions.https.HttpsError('permission-denied','Must be an administrative user to initiate delete.');}constpath=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'.awaitfirebase_tools.firestore.delete(path,{project:process.env.GCLOUD_PROJECT,recursive:true,force:true,token:functions.config().fb.token});return{path:path};});
لاستدعاء الدالة، احصل على مرجع للدالة من حزمة تطوير البرامج (SDK) الخاصة بمنصة Firebase
وامرر المَعلمات المطلوبة:
الويب
/** * Call the 'recursiveDelete' callable function with a path to initiate * a server-side delete. */functiondeleteAtPath(path){vardeleteFn=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);});}
ملاحظة: لا يتوفّر هذا المنتج على watchOS واستهدافات App Clip.
// Snippet not yet written
Objective-C
ملاحظة: لا يتوفّر هذا المنتج على watchOS واستهدافات App Clip.
// Snippet not yet written
Kotlin
/** * Call the 'recursiveDelete' callable function with a path to initiate * a server-side delete. */fundeleteAtPath(path:String){valdeleteFn=Firebase.functions.getHttpsCallable("recursiveDelete")deleteFn.call(hashMapOf("path"topath)).addOnSuccessListener{// Delete Success// ...}.addOnFailureListener{// Delete Failed// ...}}
/** * Call the 'recursiveDelete' callable function with a path to initiate * a server-side delete. */publicvoiddeleteAtPath(Stringpath){Map<String,Object>data=newHashMap<>();data.put("path",path);HttpsCallableReferencedeleteFn=FirebaseFunctions.getInstance().getHttpsCallable("recursiveDelete");deleteFn.call(data).addOnSuccessListener(newOnSuccessListener<HttpsCallableResult>(){@OverridepublicvoidonSuccess(HttpsCallableResulthttpsCallableResult){// Delete Success// ...}}).addOnFailureListener(newOnFailureListener(){@OverridepublicvoidonFailure(@NonNullExceptione){// Delete failed// ...}});}
باستخدام حزمة تطوير البرامج (SDK) للعميل من أجل دوال السحابة الإلكترونية القابلة للاستدعاء، يتم تمرير حالة مصادقة المستخدم والمعلَمة path بسلاسة إلى الدالة البعيدة.
عند اكتمال الدالة، سيتلقّى العميل رد اتصال يتضمّن النتيجة أو استثناءً. لمعرفة كيفية استدعاء دالة سحابية من Android أو Apple أو أي منصة أخرى، يمكنك الاطّلاع على المستندات.
القيود
يوضّح الحلّ الموضّح أعلاه كيفية حذف المجموعات من دالة قابلة للاستدعاء، ولكن يجب الانتباه إلى القيود التالية:
الاتساق: يحذف الرمز البرمجي أعلاه المستندات واحدًا تلو الآخر. إذا أجريت طلب بحث أثناء عملية حذف مستمرة، قد تعكس النتائج حالة غير مكتملة جزئيًا حيث يتم حذف بعض المستندات المستهدَفة فقط.
ولا يمكن أيضًا ضمان نجاح عمليات الحذف أو فشلها بشكل موحّد، لذا عليك الاستعداد للتعامل مع حالات الحذف الجزئي.
مهلات: تم ضبط الدالة أعلاه على أن تعمل لمدة 540 ثانية كحد أقصى قبل انتهاء المهلة. يمكن لرمز الحذف حذف 4,000 مستند في الثانية في أفضل الحالات. إذا كنت بحاجة إلى حذف أكثر من 2,000,000 مستند، ننصحك بتنفيذ العملية على الخادم الخاص بك حتى لا تنتهي مهلتها. للاطّلاع على مثال حول كيفية حذف مجموعة من الخادم الخاص بك، راجِع حذف المجموعات.
قد يؤدي حذف عدد كبير من المستندات إلى بطء تحميل عارض البيانات في Google Cloud Console أو عرض خطأ انتهاء المهلة.
تاريخ التعديل الأخير: 2025-08-31 (حسب التوقيت العالمي المتفَّق عليه)
[null,null,["تاريخ التعديل الأخير: 2025-08-31 (حسب التوقيت العالمي المتفَّق عليه)"],[],[],null,["\u003cbr /\u003e\n\nThe page describes how to use a callable Cloud Function\nto delete data. Once you deploy this function,\nyou can call it directly from your mobile app or website to\nrecursively delete documents and collections. For example, you can use this\nsolution to give select users the ability to delete entire collections.\n\nFor other ways to delete collections, see [Delete data](../manage-data/delete-data#collections).\n\nSolution: Delete data with a callable Cloud Function\n\nDeleting entire collections from a resource-limited mobile app can be difficult\nto implement for the following reasons:\n\n- There is no operation that atomically deletes a collection.\n- Deleting a document does not delete the documents in its subcollections.\n- If your documents have dynamic subcollections, it can be hard to know what data to delete for a given path.\n- Deleting a collection of more than 500 documents requires multiple batched write operations or hundreds of single deletes.\n- In many apps, it isn't appropriate to give end-users permission to delete entire collections.\n\nFortunately, you can write a [callable Cloud Function](https://firebase.google.com/docs/functions/callable)\nto run safe and performant deletes of entire collections or collection trees. The Cloud Function below implements a [callable function](https://firebase.google.com/docs/functions/callable)\nwhich means it can be called directly from your mobile app or website as you\nwould for a local function.\n\nTo deploy the function and try a demo, see the [sample code](https://github.com/firebase/snippets-node/tree/master/firestore/solution-deletes).\n\nCloud Function\n\nThe Cloud Function below deletes a collection and all of its descendants.\n\nInstead of implementing your own recursive delete logic for your Cloud Function,\nyou can take advantage of the `firestore:delete` command in the\nFirebase Command Line Interface (CLI). You can import any function of the\nFirebase CLI into your Node.js application using the `firebase-tools` package.\n| **Note:** Deleting data with the Firebase CLI incurs read and delete costs. For more information, see [Pricing](https://firebase.google.com/docs/firestore/pricing).\n\nThe Firebase CLI uses the Cloud Firestore REST API\nto find all documents under the specified path and delete them individually.\nThis implementation requires no knowledge of your app's specific data hierarchy\nand will even find and delete \"orphaned\" documents that no longer have a\nparent. \n\nNode.js \n\n```javascript\n/**\n * Initiate a recursive delete of documents at a given path.\n * \n * The calling user must be authenticated and have the custom \"admin\" attribute\n * set to true on the auth token.\n * \n * This delete is NOT an atomic operation and it's possible\n * that it may fail after only deleting some documents.\n * \n * @param {string} data.path the document or collection path to delete.\n */\nexports.recursiveDelete = functions\n .runWith({\n timeoutSeconds: 540,\n memory: '2GB'\n })\n .https.onCall(async (data, context) =\u003e {\n // Only allow admin users to execute this function.\n if (!(context.auth && context.auth.token && context.auth.token.admin)) {\n throw new functions.https.HttpsError(\n 'permission-denied',\n 'Must be an administrative user to initiate delete.'\n );\n }\n\n const path = data.path;\n console.log(\n `User ${context.auth.uid} has requested to delete path ${path}`\n );\n\n // Run a recursive delete on the given document or collection path.\n // The 'token' must be set in the functions config, and can be generated\n // at the command line by running 'firebase login:ci'.\n await firebase_tools.firestore\n .delete(path, {\n project: process.env.GCLOUD_PROJECT,\n recursive: true,\n force: true,\n token: functions.config().fb.token\n });\n\n return {\n path: path \n };\n });https://github.com/firebase/snippets-node/blob/f1869eeb97c2bbb713aff3deb5a67666da7bcb6b/firestore/solution-deletes/functions/index.js#L29-L73\n```\n\nClient Invocation\n\nTo call the function, get a reference to the function from the Firebase SDK\nand pass the required parameters: \n\nWeb \n\n```javascript\n/**\n * Call the 'recursiveDelete' callable function with a path to initiate\n * a server-side delete.\n */\nfunction deleteAtPath(path) {\n var deleteFn = firebase.functions().httpsCallable('recursiveDelete');\n deleteFn({ path: path })\n .then(function(result) {\n logMessage('Delete success: ' + JSON.stringify(result));\n })\n .catch(function(err) {\n logMessage('Delete failed, see console,');\n console.warn(err);\n });\n}https://github.com/firebase/snippets-node/blob/f1869eeb97c2bbb713aff3deb5a67666da7bcb6b/firestore/solution-deletes/public/index.js#L4-L18\n```\n\nSwift \n**Note:** This product is not available on watchOS and App Clip targets. \n\n```swift\n // Snippet not yet written\n \n```\n\nObjective-C \n**Note:** This product is not available on watchOS and App Clip targets. \n\n```objective-c\n // Snippet not yet written\n \n```\n\nKotlin \n\n```kotlin\n/**\n * Call the 'recursiveDelete' callable function with a path to initiate\n * a server-side delete.\n */\nfun deleteAtPath(path: String) {\n val deleteFn = Firebase.functions.getHttpsCallable(\"recursiveDelete\")\n deleteFn.call(hashMapOf(\"path\" to path))\n .addOnSuccessListener {\n // Delete Success\n // ...\n }\n .addOnFailureListener {\n // Delete Failed\n // ...\n }\n}https://github.com/firebase/snippets-android/blob/cc307b137a106d66a52fa6e9bee6f4f55dab9f76/firestore/app/src/main/java/com/google/example/firestore/kotlin/SolutionDeletes.kt#L9-L24\n```\n\nJava \n\n```java\n/**\n * Call the 'recursiveDelete' callable function with a path to initiate\n * a server-side delete.\n */\npublic void deleteAtPath(String path) {\n Map\u003cString, Object\u003e data = new HashMap\u003c\u003e();\n data.put(\"path\", path);\n\n HttpsCallableReference deleteFn =\n FirebaseFunctions.getInstance().getHttpsCallable(\"recursiveDelete\");\n deleteFn.call(data)\n .addOnSuccessListener(new OnSuccessListener\u003cHttpsCallableResult\u003e() {\n @Override\n public void onSuccess(HttpsCallableResult httpsCallableResult) {\n // Delete Success\n // ...\n }\n })\n .addOnFailureListener(new OnFailureListener() {\n @Override\n public void onFailure(@NonNull Exception e) {\n // Delete failed\n // ...\n }\n });\n}https://github.com/firebase/snippets-android/blob/cc307b137a106d66a52fa6e9bee6f4f55dab9f76/firestore/app/src/main/java/com/google/example/firestore/SolutionDeletes.java#L17-L42\n```\n\nBy using the client SDK for callable cloud functions, the users's authentication\nstate and the `path` parameter are seamlessly passed to the remote function.\nWhen the function completes, the client will receive a callback with the\nresult or an exception. To learn about how to call a cloud function from\nAndroid, Apple, or another platform, read [the documentation](https://firebase.google.com/docs/functions/callable#call_the_function).\n| **Warning:** Callable functions are not secure by default! Make sure that your callable functions check the user's authorization before performing any sensitive actions like writing or deleting documents.\n\nLimitations\n\nThe solution shown above demonstrates deleting collections from a callable\nfunction, but you should be aware of the following limitations:\n\n- **Consistency** - the code above deletes documents one at a time. If you query while there is an ongoing delete operation, your results may reflect a partially complete state where only some targeted documents are deleted. There is also no guarantee that the delete operations will succeed or fail uniformly, so be prepared to handle cases of partial deletion.\n- **Timeouts** - the function above is configured to run for a maximum of 540 seconds before timing out. The deletion code can delete 4000 documents per second in the best case. If you need to delete more than 2,000,000 documents, you should consider running the operation on your own server so that it does not time out. For an example of how to delete a collection from your own server, see [Delete collections](../manage-data/delete-data#collections).\n- Deleting a large number of documents might cause the data viewer in the Google Cloud console to load slowly or to return a timeout error."]]