باستخدام 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 ... });
قراءة البيانات وكتابتها
عند تشغيل وظيفة، فإنّها توفّر لقطة للبيانات المرتبطة بالحدث. يمكنك استخدام هذه اللقطة للقراءة من المستند الذي أدّى إلى تشغيل الحدث أو الكتابة إليه، أو استخدام "حزمة تطوير البرامج (SDK) للمشرف" في Firebase للوصول إلى أجزاء أخرى من قاعدة البيانات.
بيانات الأحداث
قراءة البيانات
عند تشغيل وظيفة، قد تحتاج إلى الحصول على بيانات من مستند تم تعديله، أو الحصول على البيانات قبل التعديل. يمكنك الحصول على البيانات السابقة باستخدام 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 هذا من
حزمة تطوير البرامج (SDK) لمنصة Cloud Firestore على Node.js
ويتضمّن طرقًا مثل 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 يتم تنفيذ في بيئة موثوق بها، ما يعني أنّها مسموح لها بالعمل كحساب خدمة في مشروعك. يمكنك إجراء عمليات القراءة والكتابة باستخدام "حزمة تطوير البرامج (SDK) للمشرف" في Firebase:
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 تتطلب (الجيل الأول) قاعدة بيانات "(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 المعنيّة
- يمكنك إيقاف التسجيل نفسه باستخدام الاستثناءات ولكن يُرجى العِلم أنّه لن يتم تسليم الأحداث المخالفة.