باستخدام Cloud Functions، يمكنك معالجة الأحداث في Cloud Firestore بدون الحاجة إلى تعديل رمز العميل. يمكنك إجراء تغييرات على Cloud Firestore من خلال الـ واجهة لقطة المستند أو من خلال الـ "حزمة تطوير البرامج (SDK) للمشرف".
في دورة حياة نموذجية، تنفّذ دالة Cloud Firestore ما يلي:
- تنتظر إجراء تغييرات على مستند معيّن.
- يتم تشغيلها عند وقوع حدث وتنفّذ مهامها.
- تتلقّى عنصر بيانات يحتوي على لقطة للبيانات المخزّنة في المستند المحدّد. بالنسبة إلى أحداث الكتابة أو التعديل، يحتوي عنصر البيانات على لقطتَين تمثّلان حالة البيانات قبل الحدث الذي أدّى إلى تشغيل الدالة وبعده.
يمكن أن تؤدي المسافة بين موقع مثيل Firestore وموقع الدالة إلى حدوث تأخير كبير في الشبكة. لتحسين الأداء، ننصحك بتحديد موقع الدالة حيثما ينطبق ذلك.
مشغّلات دالة Cloud Firestore
تصدِّر حزمة تطوير البرامج (SDK) لمنصة Cloud Functions for Firebase كائن functions.firestore
يتيح لك إنشاء معالِجات مرتبطة بأحداث معيّنة في Cloud Firestore.
| نوع الحدث | مشغّل |
|---|---|
onCreate |
يتم تشغيله عند كتابة مستند للمرة الأولى. |
onUpdate |
يتم تشغيله عندما يكون مستند موجودًا وتتغيّر أي قيمة فيه. |
onDelete |
يتم تشغيله عند حذف مستند يحتوي على بيانات. |
onWrite |
يتم تشغيله عند تشغيل onCreate أو onUpdate أو onDelete. |
إذا لم يكن لديك مشروع مفعَّل في Cloud Functions for Firebase بعد، يُرجى قراءة مقالة البدء: كتابة الدوال الأولى ونشرها لإعداد مشروع Cloud Functions for Firebase.
كتابة الدوال التي يتم تشغيلها في Cloud Firestore
تحديد مشغّل دالة
لتحديد مشغّل Cloud Firestore، حدِّد مسار مستند ونوع حدث:
Node.js
const functions = require('firebase-functions');
exports.myFunction = functions.firestore
.document('my-collection/{docId}')
.onWrite((change, context) => { /* ... */ });
يمكن أن تشير مسارات المستندات إلى مستند معيّن أو إلى نمط حرف بدل.
تحديد مستند واحد
إذا كنت تريد تشغيل حدث عند إجراء أي تغيير على مستند معيّن، يمكنك استخدام الدالة التالية.
Node.js
// Listen for any change on document `marie` in collection `users` exports.myFunctionName = functions.firestore .document('users/marie').onWrite((change, context) => { // ... Your code here });
تحديد مجموعة من المستندات باستخدام أحرف البدل
إذا كنت تريد إرفاق مشغّل بمجموعة من المستندات، مثل أي مستند في مجموعة معيّنة، استخدِم {wildcard} بدلاً من رقم تعريف المستند:
Node.js
// Listen for changes in all documents in the 'users' collection exports.useWildcard = functions.firestore .document('users/{userId}') .onWrite((change, context) => { // If we set `/users/marie` to {name: "Marie"} then // context.params.userId == "marie" // ... and ... // change.after.data() == {name: "Marie"} });
في هذا المثال، عندما يتم تغيير أي حقل في أي مستند في users، يتم مطابقته مع حرف بدل يُسمى userId.
إذا كان أحد المستندات في users يحتوي على مجموعات فرعية، وتم تغيير حقل في أحد مستندات هذه المجموعات الفرعية، لن يتم تشغيل حرف البدل userId.
يتم استخراج المطابقات مع أحرف البدل من مسار المستند وتخزينها في context.params.
يمكنك تحديد أي عدد تريده من أحرف البدل لاستبدال أرقام تعريف المجموعات أو المستندات الصريحة، مثلاً:
Node.js
// Listen for changes in all documents in the 'users' collection and all subcollections exports.useMultipleWildcards = functions.firestore .document('users/{userId}/{messageCollectionId}/{messageId}') .onWrite((change, context) => { // If we set `/users/marie/incoming_messages/134` to {body: "Hello"} then // context.params.userId == "marie"; // context.params.messageCollectionId == "incoming_messages"; // context.params.messageId == "134"; // ... and ... // change.after.data() == {body: "Hello"} });
مشغّلات الأحداث
تشغيل دالة عند إنشاء مستند جديد
يمكنك تشغيل دالة في أي وقت يتم فيه إنشاء مستند جديد في مجموعة
باستخدام معالِج onCreate() مع حرف بدل.
تستدعي دالة المثال هذه createUser في كل مرة تتم فيها إضافة ملف شخصي لمستخدم جديد:
Node.js
exports.createUser = functions.firestore .document('users/{userId}') .onCreate((snap, context) => { // Get an object representing the document // e.g. {'name': 'Marie', 'age': 66} const newValue = snap.data(); // access a particular field as you would any JS property const name = newValue.name; // perform desired operations ... });
تشغيل دالة عند تعديل مستند
يمكنك أيضًا تشغيل دالة عند تعديل مستند باستخدام الدالة
onUpdate() مع حرف بدل. تستدعي دالة المثال هذه updateUser إذا غيّر مستخدم ملفه الشخصي:
Node.js
exports.updateUser = functions.firestore .document('users/{userId}') .onUpdate((change, context) => { // Get an object representing the document // e.g. {'name': 'Marie', 'age': 66} const newValue = change.after.data(); // ...or the previous value before this update const previousValue = change.before.data(); // access a particular field as you would any JS property const name = newValue.name; // perform desired operations ... });
تشغيل دالة عند حذف مستند
يمكنك أيضًا تشغيل دالة عند حذف مستند باستخدام الدالة
onDelete() مع حرف بدل. تستدعي دالة المثال هذه deleteUser عندما يحذف مستخدم ملفه الشخصي:
Node.js
exports.deleteUser = functions.firestore .document('users/{userID}') .onDelete((snap, context) => { // Get an object representing the document prior to deletion // e.g. {'name': 'Marie', 'age': 66} const deletedValue = snap.data(); // perform desired operations ... });
تشغيل دالة لجميع التغييرات التي يتم إجراؤها على مستند
إذا لم يكن نوع الحدث الذي يتم تشغيله مهمًا بالنسبة إليك، يمكنك الاستماع إلى جميع
التغييرات في مستند Cloud Firestore باستخدام الدالة onWrite()مع حرف بدل. تستدعي دالة المثال هذه modifyUser إذا تم إنشاء مستخدم أو تعديله أو حذفه:
Node.js
exports.modifyUser = functions.firestore .document('users/{userID}') .onWrite((change, context) => { // Get an object with the current document value. // If the document does not exist, it has been deleted. const document = change.after.exists ? change.after.data() : null; // Get an object with the previous document value (for update or delete) const oldDocument = change.before.data(); // perform desired operations ... });
قراءة البيانات وكتابتها
عند تشغيل دالة، فإنّها توفّر لقطة للبيانات المرتبطة بالحدث. يمكنك استخدام هذه اللقطة للقراءة من المستند الذي أدّى إلى تشغيل الحدث أو الكتابة إليه، أو استخدام حزمة Firebase Admin SDK للوصول إلى أجزاء أخرى من قاعدة البيانات.
بيانات الأحداث
قراءة البيانات
عند تشغيل دالة، قد تحتاج إلى الحصول على بيانات من مستند تم تعديله، أو الحصول على البيانات قبل التعديل. يمكنك الحصول على البيانات السابقة باستخدام change.before.data()، التي تحتوي على لقطة المستند قبل التعديل.
وبالمثل، تحتوي change.after.data() على حالة لقطة المستند بعد التعديل.
Node.js
exports.updateUser2 = functions.firestore .document('users/{userId}') .onUpdate((change, context) => { // Get an object representing the current document const newValue = change.after.data(); // ...or the previous value before this update const previousValue = change.before.data(); });
يمكنك الوصول إلى الخصائص كما تفعل في أي كائن آخر. بدلاً من ذلك، يمكنك استخدام الدالة get للوصول إلى حقول معيّنة:
Node.js
// Fetch data using standard accessors const age = snap.data().age; const name = snap.data()['name']; // Fetch data using built in accessor const experience = snap.get('experience');
كتابة البيانات
يرتبط كل استدعاء دالة بمستند معيّن في قاعدة بيانات Cloud Firestore. يمكنك الوصول إلى هذا المستند كـ DocumentReference في السمة ref للقطة التي يتم عرضها على الدالة.
يأتي DocumentReference هذا من
حزمة Cloud Firestore Node.js SDK
ويتضمّن طرقًا مثل update() وset() وremove() لتتمكّن من تعديل المستند الذي أدّى إلى تشغيل الدالة بسهولة.
Node.js
// Listen for updates to any `user` document. exports.countNameChanges = functions.firestore .document('users/{userId}') .onUpdate((change, context) => { // Retrieve the current and previous value const data = change.after.data(); const previousData = change.before.data(); // We'll only update if the name has changed. // This is crucial to prevent infinite loops. if (data.name == previousData.name) { return null; } // Retrieve the current count of name changes let count = data.name_change_count; if (!count) { count = 0; } // Then return a promise of a set operation to update the count return change.after.ref.set({ name_change_count: count + 1 }, {merge: true}); });
البيانات خارج حدث المشغّل
Cloud Functions يتم تنفيذ في بيئة موثوق بها، ما يعني أنّها مخوّلة بصفتها حساب خدمة في مشروعك. يمكنك إجراء عمليات القراءة والكتابة باستخدام حزمة Firebase Admin SDK:
Node.js
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();
exports.writeToFirestore = functions.firestore
.document('some/doc')
.onWrite((change, context) => {
db.doc('some/otherdoc').set({ ... });
});
القيود
يُرجى ملاحظة القيود التالية لمشغّلات Cloud Firestore في Cloud Functions:
- Cloud Functions (الجيل الأول) تتطلّب قاعدة بيانات "(default)" حالية في وضع Firestore الأصلي. لا تتيح قواعد البيانات المُسمّاة Cloud Firestoreأو وضع Datastore. يُرجى استخدام Cloud Functions (الجيل الثاني) لإعداد الأحداث في مثل هذه الحالات.
- يُعدّ الإعداد بين المشاريع باستخدام Cloud Functions ومشغّل Cloud Firestore قيدًا. لإعداد مشغّل Cloud Firestore، يجب أن تكون Cloud Functions في المشروع نفسه.
- لا نضمن الترتيب. يمكن أن تؤدي التغييرات السريعة إلى تشغيل استدعاءات الدوال بترتيب غير متوقّع.
- يتم تسليم الأحداث مرة واحدة على الأقل، ولكن قد يؤدي حدث واحد إلى استدعاءات متعددة للدالة. تجنَّب الاعتماد على آليات التنفيذ مرة واحدة بالضبط، واكتب دوالاً لا تتأثر بتكرار تنفيذها.
- يتطلّب Cloud Firestore في وضع Datastore استخدام Cloud Functions (الجيل الثاني). Cloud Functions (الجيل الأول) لا تتيح وضع Datastore.
- يرتبط المشغّل بقاعدة بيانات واحدة. لا يمكنك إنشاء مشغّل يطابق قواعد بيانات متعددة.
- لا يؤدي حذف قاعدة بيانات إلى حذف أي مشغّلات لهذه قاعدة البيانات تلقائيًا. يتوقف المشغّل عن تسليم الأحداث ولكنه يظل موجودًا إلى أن تحذفه.
- إذا تجاوز حدث مطابق الحد الأقصى لحجم الطلب، قد لا يتم تسليم الـ
حدث إلى Cloud Functions (الجيل الأول).
- يتم تسجيل الأحداث التي لم يتم تسليمها بسبب حجم الطلب في سجلّات النظام الأساسي ويتم احتسابها ضمن استخدام السجلّات للمشروع.
- يمكنك العثور على هذه السجلّات في "مستكشف السجلّات" مع الرسالة "لا يمكن تسليم الحدث إلى
دالة السحابة الإلكترونية بسبب تجاوز الحجم الحدّ الأقصى للجيل الأول..." بمستوى خطورة
error. يمكنك العثور على اسم الدالة ضمن الحقلfunctionName. إذا كان الحقل thereceiveTimestampلا يزال ضمن ساعة من الآن، يمكنك استنتاج محتوى الحدث الفعلي من خلال قراءة المستند المعنيّ باستخدام لقطة قبل الطابع الزمني وبعده. - لتجنُّب مثل هذه الوتيرة، يمكنك:
- نقل البيانات والترقية إلى Cloud Functions (الجيل الثاني)
- تقليل حجم المستند
- حذف Cloud Functions المعنيّة
- يمكنك إيقاف التسجيل نفسه باستخدام الاستثناءات ولكن يُرجى العِلم أنّه لن يتم تسليم الأحداث المخالفة.