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

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

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

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

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

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

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

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

لإنشاء مصدر بيانات التغييرات، استخدِم Google Cloud Console.

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

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

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

عرض "مصادر بيانات التغييرات"

يمكنك عرض تفاصيل عن "مصادر بيانات التغييرات" في Google Cloud Console.

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

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

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

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

لحذف مصدر بيانات التغييرات، استخدِم Google Cloud Console.

  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.

تستفيد ميزة "مصادر بيانات التغييرات" من فترة 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.

لا تتطلّب هذه الميزة ميزة PITR وتُجري عملية بحث عن المستند.

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 }}
  }]);

ميزة "مصادر بيانات التغييرات" والنسخ الاحتياطية

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

الفوترة

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

يصف القسم التالي الاختلافات في ميزة "مصادر بيانات التغييرات" بين 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: []
}

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