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

تتيح ميزة "تغييرات البث" في Firestore المتوافقة مع MongoDB للتطبيقات الوصول إلى التغييرات في الوقت الفعلي (عمليات الإدراج والتعديل والحذف) التي يتم إجراؤها على مجموعة أو قاعدة بيانات بأكملها. يرتّب مصدر بيانات التغيير التعديلات حسب وقت التعديل.

يمكن الوصول إلى Change Streams من خلال واجهات برمجة التطبيقات المتوافقة مع MongoDB وبرامج تشغيل MongoDB التقليدية. يمكن لتنفيذ Change Streams المتوافق مع 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.

الأدوار والأذونات

لإنشاء "قنوات تغيير" وحذفها وإدراجها، يجب أن يكون لدى الجهة الرئيسية أذونات 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"
})

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

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