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

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

يمكن الوصول إلى Change Streams من خلال واجهات برمجة التطبيقات المتوافقة مع MongoDB وبرامج تشغيل MongoDB التقليدية. يمكن لعملية تنفيذ "مؤشرات التغيير" في Firestore المتوافقة مع MongoDB التعامل مع أي معدل نقل بيانات لعمليات الكتابة والقراءة من خلال تنفيذ فريد لعملية التقسيم التلقائي لعمليات الكتابة والقراءة المتوازية. يتيح لك ذلك إنشاء أعباء عمل بمعدّل أعلى لنقل البيانات. يمكنك أيضًا تحسين البنية الأساسية لنقل البيانات ومزامنتها بين Cloud Firestore وحلول التخزين الأخرى.

بالإضافة إلى التوافق مع برامج تشغيل MongoDB، يمكنك استخدام Cloud Firestore لقراءة "موجزات التغيير" بالتوازي. يتيح لك ذلك إنشاء أعباء عمل متوازية لقراءة البيانات بمعدّل نقل بيانات أعلى. ويمثّل كل مصدر قسمًا موزّعًا بشكل جيد من النتائج.

تتيح ميزة "موجزات التغيير" الميزات التالية:

  • ميزة "موجزات التغيير" (Change streams) القابلة للضبط على مستوى قاعدة البيانات أو المجموعة
  • مدة الاحتفاظ ببيانات مصدر التغيير المحدّدة عند الإنشاء فترة الاحتفاظ التلقائية بالبيانات هي 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.

ضبط سلاسل التغييرات

لإنشاء مجموعات بيانات Change Streams حالية لقاعدة بيانات أو حذفها أو عرضها، استخدِم وحدة تحكّم Google Cloud.

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

لإنشاء مجموعات بيانات التغيير وحذفها وإدراجها، يحتاج المستخدم الرئيسي إلى أذونات "إدارة الهوية وإمكانية الوصول" (IAM) التالية: datastore.schemas.create وdatastore.schemas.delete وdatastore.schemas.list على التوالي.

على سبيل المثال، يمنح دور مشرف فهرس مخزن البيانات (roles/datastore.indexAdmin) هذه الأذونات.

إنشاء مصدر بيانات تغيير

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

لإنشاء مجموعة بيانات تغييرات، استخدِم وحدة تحكّم Google Cloud.

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

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

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

عرض سلاسل التغييرات

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

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

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

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

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

لحذف مجموعة بيانات تغيير، استخدِم وحدة تحكّم Google Cloud.

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

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

  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.

تستفيد ميزة "متابعة التغييرات" من نافذة "الاستعادة في نقطة زمنية محدّدة" لتوفير عرض للمستند قبل حدث التغيير المحدّد وبعده. By default, update events contain an updateDescription field which is the delta of the fields modified by the update operation.

لتضمين الصور السابقة واللاحقة في حدث تغيير، يجب تحديد الخيارين 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",
})

Parallel Reads

لزيادة معدّل النقل، يمكنك استخدام الخيار 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 والنسخ الاحتياطية

لا تتوفّر إعدادات مجموعة بيانات التغيير ولا بيانات مجموعة بيانات التغيير في عمليات استعادة النُسخ الاحتياطية. في حال استعادة قاعدة بيانات باستخدام "سلاسل التغيير"، عليك إعادة إنشاء سلاسل التغيير هذه في قاعدة البيانات الوجهة لفتح المؤشرات إلى قاعدة البيانات هذه.

الفوترة

الاختلافات في السلوك

يوضّح القسم التالي الاختلافات في سلاسل التغييرات بين 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: []
}

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