تتيح ميزة "تغييرات البيانات" في Firestore المتوافقة مع MongoDB للتطبيقات الوصول إلى التغييرات التي يتم إجراؤها في الوقت الفعلي (عمليات الإدراج والتعديل والحذف) على مجموعة أو قاعدة بيانات بأكملها. يرتّب مصدر بيانات التغيير التعديلات حسب وقت التعديل.
يمكن الوصول إلى Change Streams من خلال واجهات برمجة التطبيقات المتوافقة مع MongoDB وبرامج تشغيل MongoDB التقليدية. يمكن لتنفيذ ميزة "تغييرات البيانات" المتوافقة مع Firestore وMongoDB التعامل مع أي سرعة معالجة بيانات للقراءة والكتابة من خلال تنفيذ فريد لعملية التقسيم التلقائي عند الكتابة والتوازي عند القراءة. يتيح لك ذلك إنشاء أحمال عمل ذات معدل نقل بيانات مرتفع. يمكنك أيضًا تحسين البنية الأساسية لعمليات نقل البيانات ومزامنتها بين Cloud Firestore وحلول التخزين الأخرى.
بالإضافة إلى التوافق مع برامج تشغيل MongoDB، يمكنك استخدام Cloud Firestore لقراءة "قنوات تغيير البيانات" بالتوازي. يتيح لك ذلك إنشاء أعباء عمل قراءة متوازية وعالية الإنتاجية. يمثّل كل مصدر بيانات قسمًا موزّعًا بشكل جيد من النتائج.
تتيح ميزة "تدفقات التغيير" الميزات التالية:
- يمكن ضبط "مصادر تغيير" بنطاق قاعدة البيانات أو المجموعة.
- مدة الاحتفاظ ببيانات "مجرى تغيير" يتم تحديدها عند الإنشاء مدة الاحتفاظ التلقائية هي 7 أيام والحد الأدنى لمدة الاحتفاظ هو يوم واحد. يجب أن تكون مدة الاحتفاظ بمضاعفات اليوم الواحد، وبحد أقصى 7 أيام. لا يمكن تغيير مدة الاحتفاظ بالبيانات بعد إنشائها. لتغيير مدة الاحتفاظ بالبيانات، عليك حذف بث تغيير البيانات وإعادة إنشائه.
- أحداث التغيير
deleteوinsertوupdateوdropالتي يمكن ملاحظتها باستخدامdb.collection.watch()وdb.watch() - يحتوي ملف
updateDescription.updatedFieldsعلى اختلافات التحديث. - جميع خيارات
fullDocumentوfullDocumentBeforeChange- جارٍ البحث عن المستند الكامل لمعرفة آخر الأخبار.
- صورة مسبقة للمستند قبل استبداله أو تعديله أو حذفه
- صورة المستند بعد استبداله أو تعديله
- تتطلّب الصور قبل وبعد ساعة واحدة تفعيل ميزة "الاسترداد في نقطة زمنية محددة" (PITR).
- جميع خيارات استئناف التشغيل، بما في ذلك
resumeAfterوstartAfter - عند استخدام
watch()لمراقبة التغييرات، يمكنك ربط مراحل التجميع، مثل$addFieldsو$matchو$projectو$replaceRootو$replaceWithو$setو$unset.
إعداد "قنوات تغيير البث"
لإنشاء أو حذف أو عرض "قنوات تغيير" حالية لقاعدة بيانات، استخدِم Google Cloud Console.
الأدوار والأذونات
لإنشاء Change Streams وحذفها وإدراجها، يجب أن يكون لدى الجهة الرئيسية أذونات
datastore.schemas.create وdatastore.schemas.delete وdatastore.schemas.list في خدمة "إدارة الهوية وإمكانية الوصول" (IAM)، على التوالي.
يمنح دور مشرف فهرس Datastore (roles/datastore.indexAdmin) هذه الأذونات، على سبيل المثال.
إنشاء مصدر بيانات لتغيير البث
قبل أن تتمكّن من فتح مؤشر مطابق لتدفق تغيير، يجب إنشاء تدفق تغيير. لا تتوفّر إمكانية تفعيل تدفق التغيير تلقائيًا عند إنشاء مجموعة أو قاعدة بيانات.
لإنشاء مصدر تغيير، استخدِم وحدة تحكّم Google Cloud.
-
في Google Cloud Console، انتقِل إلى صفحة قواعد البيانات.
- من القائمة، اختَر قاعدة بيانات متوافقة مع Firestore وMongoDB. يتم فتح لوحة Firestore Studio.
- في لوحة المستكشف، ابحث عن عقدة تغيير التدفقات، وانقر على المزيد من الإجراءات، ثم اختَر إنشاء تدفق تغيير.
- أدخِل اسمًا فريدًا لتدفق التغيير ونطاقه وفترة التخزين، ثم انقر على حفظ.
عرض "تغييرات البث"
يمكنك الاطّلاع على تفاصيل حول Change Streams في Google Cloud Console.
-
في Google Cloud Console، انتقِل إلى صفحة قواعد البيانات.
- من القائمة، اختَر قاعدة بيانات متوافقة مع Firestore وMongoDB. يتم فتح لوحة Firestore Studio.
- في لوحة المستكشف، ابحث عن العقدة تغيير التدفقات.
- لفتح العقدة أو إغلاقها، انقر على تبديل العقدة.
حذف مصدر بيانات
لحذف مصدر تغيير، استخدِم "وحدة تحكّم Google Cloud".
-
في Google Cloud Console، انتقِل إلى صفحة قواعد البيانات.
- من القائمة، اختَر قاعدة بيانات متوافقة مع Firestore وMongoDB. يتم فتح لوحة Firestore Studio.
- في لوحة المستكشف، ابحث عن العقدة تغيير التدفقات.
- لفتح العقدة أو إغلاقها، انقر على تبديل العقدة.
- في المستكشف، حدِّد موقع مصدر بيانات تغييرات البث الذي تريد حذفه.
- انقر على مزيد من الإجراءات، ثم اختَر حذف قناة تغيير.
- في مربّع الحوار، أدخِل اسم قناة تغيير البيانات لتأكيد الحذف، ثم انقر على حذف.
فتح مؤشر تغيير البيانات أو استئنافه
توضّح الأمثلة التالية كيفية إنشاء مؤشر لتدفق التغيير واستئنافه وضبطه.
قبل إنشاء مؤشر لتدفق تغييرات، يجب إنشاء تدفق تغييرات بشكل صريح لقاعدة البيانات أو المجموعة.
إنشاء مؤشر لتغيير مصدر البيانات
لإنشاء مؤشر جديد لتدفق التغيير، استخدِم طريقة watch في برامج تشغيل MongoDB.
للاستماع إلى جميع التغييرات في قاعدة بيانات، أنشئ بثًا للتغييرات على مستوى قاعدة البيانات واستدعِ طريقة watch على عنصر db.
let cursor = db.watch()
لإنشاء مؤشر محدد النطاق بمجموعة، عليك أولاً إنشاء مصدر تغييرات لهذه المجموعة. بعد ذلك، استدعِ طريقة watch في المجموعة ذات الصلة.
let cursor = db.my_collection.watch()
بعد إنشاء مؤشر لتغيير البث، يمكنك البدء في البث.
على سبيل المثال، إذا أدرجت مستندًا واستدعيت tryNext على المؤشر،
سيظهر التغيير في بث التغيير.
let doc = db.my_collection.insertOne({value: "hello world"}) console.log(cursor.tryNext())
إذا عدّلت المستند وحذفته، ستظهر هذه التغييرات في مجرى التغيير:
db.my_collection.updateOne({"_id": doc.insertedId}, {$set: {value: "hello world!"}}) db.my_collection.deleteOne({"_id": doc.insertedId}}) // Prints the update event console.log(cursor.tryNext()) // Prints the delete event console.log(cursor.tryNext())
استئناف بث التغيير
لاستئناف بث تغيير، استخدِم الخيارَين resumeAfter أو startAfter.
لتحديد الموضع الذي يجب استئناف عملية الترحيل منه في سجلّ التغيير resumeAfter وstartAfter، استخدِم رمزًا مميزًا للاستئناف.
// Create a cursor and add one event to the change stream. let cursor = db.my_collection.watch(); db.my_collection.insertOne({value: "hello world"}); let event = cursor.tryNext(); // Get the resume token from the event. let resumeToken = event._id; // Add a new event to the change stream. db.my_collection.insertOne({value: "foobar"}); // Create a new cursor by using the resume token as a starting point. let newCursor = db.my_collection.watch({resumeAfter: resumeToken}) // Log the change event containing the "foobar" value. console.log(newCursor.tryNext())
لاستخدام startAfter:
// Start after the resume token. let startAfterCursor = db.my_collection.watch({startAfter: resumeToken})
تضمين صور قبل وبعد التعديل في التحديثات والحذف
إذا لزم الأمر، يمكنك تضمين صور للمستندات قبل وبعد التعديل في أحداث التغيير الخاصة بالتعديل والحذف. تخضع إمكانية الوصول إلى الصور لفترة الاسترداد في نقطة زمنية محددة (PITR)، ولقراءة صور المستندات التي مرّ عليها أكثر من ساعة، يجب تفعيل ميزة الاسترداد في نقطة زمنية محددة.
تستفيد "مصادر بيانات تغيير" من نافذة PITR لتقديم عرض للمستند قبل حدث التغيير المحدّد وبعده. تحتوي أحداث التعديل تلقائيًا على الحقل updateDescription الذي يمثّل الفرق بين الحقول التي تم تعديلها من خلال عملية التعديل.
لتضمين الصور قبل وبعد في حدث تغيير، يجب تحديد الخيارَين fullDocumentBeforeChange وfullDocument في طلب البحث عن بث التغييرات.
let cursor = db.my_collection.watch({ "fullDocument": "required", "fullDocumentBeforeChange": "required" })
إذا حاولت طلب البحث قراءة مستند خارج فترة الاحتفاظ ببيانات الاسترداد في نقطة زمنية محددة أو إذا لم تكن ميزة الاسترداد في نقطة زمنية محددة مفعّلة، سيؤدي ذلك إلى ظهور رسالة خطأ من جهة الخادم.required
كبديل لعرض خطأ، يمكنك استخدام القيمة whenAvailable لعرض القيمة null إذا لم تعُد الصور متاحة.
let cursor = db.my_collection.watch({ "fullDocument": "whenAvailable", "fullDocumentBeforeChange": "whenAvailable" })
تضمين الصورة الحالية في التحديثات
تحتوي أحداث التعديل تلقائيًا على حقل updateDescription يمثّل الفرق بين الحقول التي تم تعديلها من خلال عملية التعديل. للبحث بدلاً من ذلك عن أحدث إصدار من المستند بأكمله، استخدِم القيمة updateLookup في الخيار fullDocument.
لا تتطلّب هذه الميزة استعادة البيانات في نقطة زمنية معيّنة، بل تبحث عن المستند.
let cursor = db.my_collection.watch({ "fullDocument": "updateLookup", })
عمليات القراءة المتوازية
لزيادة سرعة معالجة البيانات، يمكنك استخدام الخيار firestoreWorkerConfig لتقسيم طلب بحث عن تغييرات في البيانات على عدة عمليات عاملة. يكون كل عامل مسؤولاً عن عرض التغييرات لمجموعة مميزة من المستندات. يجب إنشاء مؤشر متوازٍ من خلال طلب بحث runCommand أو aggregate.
على سبيل المثال، يمكنك توزيع مصدر تغيير على 3 عوامل على النحو التالي:
let cursor1 = db.my_collection.aggregate([{ "$changeStream": { "firestoreWorkerConfig": {numWorkers: 3, workerId: 0 }} }]); let cursor2 = db.my_collection.aggregate([{ "$changeStream": { "firestoreWorkerConfig": {numWorkers: 3, workerId: 1 }} }]); let cursor3 = db.my_collection.aggregate([{ "$changeStream": { "firestoreWorkerConfig": {numWorkers: 3, workerId: 2 }} }]);
عمليات تغيير البث والاحتفاظ بنسخة احتياطية
لا يتوفّر كلّ من إعدادات مصدر البيانات المتغيّرة وبيانات مصدر البيانات المتغيّرة في عمليات الاحتفاظ بنسخة احتياطية واستعادتها. في حال استعادة قاعدة بيانات تتضمّن Change Streams، عليك إعادة إنشاء مصادر البيانات هذه في قاعدة البيانات الوجهة لفتح المؤشرات إلى قاعدة البيانات هذه.
الفوترة
- تتضمّن Change Streams تكاليف وحدات القراءة والتخزين. اطّلِع على أسعار "تغيير البث".
- لتضمين صور قبل وبعد أقدم من ساعة واحدة في وقت طلب القراءة، يجب تفعيل ميزة "الاسترداد في نقطة زمنية" التي تتكبّد تكاليف الاسترداد في نقطة زمنية.
الاختلافات في السلوك
يوضّح القسم التالي الاختلافات في Change Streams بين Firestore المتوافق مع MongoDB وMongoDB.
updateDescription
updateDescription هو مستند في حدث update يصف الحقول التي تم تعديلها أو إزالتها من خلال عملية التعديل. في
Cloud Firestore، الاختلافات البارزة هي:
- في
updateDescription، لا تتم تعبئة الحقلَينtruncatedArraysوdisambiguatedPaths. updateDescription.updatedFieldsتمثّل اختلافًا أساسيًا بين الصور قبل وبعد تطبيق تغيير على مستند.
إليك الحالة الأولية التالية لمستند:
db.my_collection.insertOne({ _id: 1, root: { array: [{a: 1}, {b: 2}, {c: 3}] } })
السيناريو 1: تغيير العنصر الأول فقط في المصفوفة
في هذا السيناريو، يتطابق سلوك Cloud Firestore مع MongoDB.
db.my_collection.updateOne( {_id: 1}, {'$set': {"root.array.0.a": 100}} ) { updatedFields: {"root.array.0.a": 100}, removedFields: [] }
السيناريو 2: الكتابة فوق البيانات باستخدام مصفوفة كاملة
في هذه الحالة، تعدّل العملية حقل المصفوفة الأول فقط، ولكنها تستبدل المصفوفة بأكملها.
لا يفرّق Cloud Firestore بين هاتين الحالتين ويعرض updateDescription.updatedFields نفسه في كلتيهما:
db.my_collection.updateOne( {_id: 1}, {'$set': {"root.array": [{a: 100}, {b: 2}, {c: 3}]}} ) // In other implementations, updatedFields reflects the mutation itself { updatedFields: { "root.array": [{a: 100}, {b: 2}, {c: 3}] }, removedFields: [] } // Firestore updatedFields is the diff between the before and after versions of the document { updatedFields: {"root.array.0.a": 100}, removedFields: [] }