خواندن داده‌های هم‌زمان با جاری‌سازی‌های تغییر

«جریان‌های تغییر» برای Firestore با سازگاری MongoDB به برنامه‌ها اجازه می‌دهد به تغییرات هم‌زمان (درج، به‌روزرسانی، و حذف) ایجادشده در مجموعه یا کل پایگاه داده دسترسی داشته باشند. جریان تغییر به‌روزرسانی‌ها را براساس زمان اصلاح مرتب می‌کند.

Change Streams ازطریق میاناهای برنامه‌سازی کاربردی سازگار با MongoDB و «درایورهای» سنتی MongoDB قابل‌دسترسی است. پیاده‌سازی Firestore با سازگاری MongoDB از «جریان‌های تغییر» می‌تواند هر توان عملیاتی نوشتن و خواندن را ازطریق پیاده‌سازی منحصربه‌فرد پارتیشن‌بندی خودکار در نوشتن و موازی‌سازی خواندن مدیریت کند. این به شما امکان می‌دهد حجم‌های کاری با توان گذرداد بالا بسازید. همچنین می‌توانید زیرساخت همگام‌سازی داده و انتقال را بین Cloud Firestore و دیگر راه‌حل‌های ذخیره‌سازی بهبود دهید.

علاوه‌بر سازگاری با درایورهای MongoDB، می‌توانید از Cloud Firestore برای خواندن موازی «جریان‌های تغییر» استفاده کنید. این به شما امکان می‌دهد حجم‌های کاری خواندن موازی با توان گذرداد بالا بسازید. هر جاری‌سازی نشان‌دهنده یک بخش‌بندی خوب توزیع‌شده از نتایج است.

«جاری‌سازی‌های تغییر» از ویژگی‌های زیر پشتیبانی می‌کند:

  • جریان‌های تغییر قابل‌پیکربندی با دامنه پایگاه داده یا مجموعه.
  • مدت نگهداری برای جاری‌سازی تغییر که در زمان ایجاد مشخص شده است. مدت نگهداری پیش‌فرض ۷ روز و حداقل مدت نگهداری ۱ روز است. مدت نگهداری باید مضربی از ۱ روز و حداکثر ۷ روز باشد. مدت نگهداری بعداز ایجاد قابل‌تغییر نیست. برای تغییر دوره نگهداری، باید جریان تغییر را حذف و دوباره ایجاد کنید.
  • ‫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 استفاده کنید.

نقش‌ها و اجازه‌ها

برای ایجاد، حذف، و فهرست کردن «جریان‌های تغییر»، مدیر اصلی به‌ترتیب به اجازه‌های datastore.schemas.create، datastore.schemas.delete، و datastore.schemas.list «مدیریت هویت و دسترسی‌ها» (IAM) نیاز دارد.

برای مثال، نقش Datastore Index Admin (roles/datastore.indexAdmin) این اجازه‌ها را اعطا می‌کند.

ایجاد کردن جریان تغییر

قبل‌از اینکه بتوانید مکان‌نمای جریان تغییر مربوطه را باز کنید، باید یک جریان تغییر ایجاد کنید. فعال‌سازی خودکار جریان تغییر در مجموعه یا پایگاه داده ایجاد پشتیبانی نمی‌شود.

برای ایجاد جریان تغییر، از کنسول Google Cloud استفاده کنید.

  1. در کنسول Google Cloud، به صفحه پایگاه‌های داده بروید.

    رفتن به پایگاه‌های داده

  2. از فهرست، پایگاه داده Firestore با سازگاری MongoDB را انتخاب کنید. پانل Firestore Studio باز می‌شود.
  3. در پانل کاوشگر، گره جاری‌سازی‌های تغییر را پیدا کنید، روی کنش‌های بیشتر کلیک کنید، و سپس ایجاد جاری‌سازی تغییر را انتخاب کنید.
  4. نام، دامنه، و دوره نگهداری منحصربه‌فردی برای جاری‌سازی تغییر وارد کنید، سپس روی ذخیره کلیک کنید

مشاهده جریان‌های تغییر

می‌توانید جزئیات مربوط به «جریان‌های تغییر» را در کنسول Google Cloud مشاهده کنید.

  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 را فعال کنید.

«جریان‌های تغییر» از پنجره 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 ایجاد کنید.

برای مثال، می‌توانید جریان تغییر را بین ۳ کارگر به این صورت توزیع کنید:

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

سناریو ۱: فقط اولین عنصر آرایه را تغییر دهید.

در این سناریو، رفتار Cloud Firestore با MongoDB مطابقت دارد.

db.my_collection.updateOne(
  {_id: 1},
  {'$set': {"root.array.0.a": 100}}
)

{
  updatedFields: {"root.array.0.a": 100},
  removedFields: []
}

سناریو ۲: رونویسی با کل آرایه

در این سناریو، عملیات فقط اولین فیلد آرایه را به‌روز می‌کند اما کل آرایه را رونویسی می‌کند.

تفاوت به‌روزرسانی 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: []
}

حالا چه می‌شود