قراءة البيانات في الوقت الفعلي باستخدام "مصادر تغيير البيانات"

تتيح ميزة "عمليات بث التغييرات" في 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 Console.

  1. في Google Cloud Console، انتقِل إلى صفحة قواعد البيانات.

    الانتقال إلى "قواعد البيانات"

  2. من القائمة، اختَر قاعدة بيانات متوافقة مع Firestore وMongoDB. يتم فتح لوحة Firestore Studio.
  3. في لوحة المستكشف، ابحث عن عقدة تغيير التدفقات، وانقر على المزيد من الإجراءات، ثم اختَر إنشاء تغيير التدفق.
  4. أدخِل اسمًا ونطاقًا وفترة التخزين فريدة لتدفق التغيير، ثم انقر على حفظ.

عرض "تغييرات البث"

يمكنك الاطّلاع على تفاصيل حول Change Streams في Google Cloud Console.

  1. في Google Cloud Console، انتقِل إلى صفحة قواعد البيانات.

    الانتقال إلى "قواعد البيانات"

  2. من القائمة، اختَر قاعدة بيانات متوافقة مع Firestore وMongoDB. يتم فتح لوحة Firestore Studio.
  3. في لوحة المستكشف، ابحث عن عقدة تغيير التدفقات.
  4. لفتح العقدة أو إغلاقها، انقر على تبديل العقدة.

حذف مصدر بيانات التغيير

لحذف مصدر تغيير، استخدِم "وحدة تحكّم Google Cloud".

  1. في Google Cloud Console، انتقِل إلى صفحة قواعد البيانات.

    الانتقال إلى "قواعد البيانات"

  2. من القائمة، اختَر قاعدة بيانات متوافقة مع Firestore وMongoDB. يتم فتح لوحة Firestore Studio.
  3. في لوحة المستكشف، ابحث عن عقدة تغيير التدفقات.
  4. لفتح العقدة أو إغلاقها، انقر على تبديل العقدة.
  5. في المستكشف، حدِّد موقع مصدر بيانات تغييرات البث الذي تريد حذفه.
  6. انقر على مزيد من الإجراءات، ثم اختَر حذف قناة تغيير.
  7. في مربّع الحوار، أدخِل اسم قناة تغيير البيانات لتأكيد الحذف، ثم انقر على حذف.

فتح مؤشر تغيير البيانات أو استئنافه

توضّح الأمثلة التالية كيفية إنشاء مؤشر تغيير البيانات واستئنافه وضبطه.

قبل إنشاء مؤشر لتدفق تغييرات، يجب إنشاء تدفق تغييرات بشكل صريح لقاعدة البيانات أو المجموعة.

إنشاء مؤشر لتدفق التغيير

لإنشاء مؤشر جديد لتدفق التغيير، استخدِم طريقة 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"
})

إذا حاولت طلب البحث قراءة مستند خارج فترة الاحتفاظ بالبيانات في PITR أو إذا لم تكن ميزة PITR مفعّلة، سيؤدي ذلك إلى ظهور رسالة خطأ من جهة الخادم.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 بين 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: []
}

الخطوات التالية