خواندن داده‌های بلادرنگ با جریان‌های تغییر

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

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

علاوه بر سازگاری با درایورهای MongoDB، می‌توانید از Cloud Firestore برای خواندن Change Streams به صورت موازی استفاده کنید. این به شما امکان می‌دهد بارهای کاری خواندن موازی و با توان عملیاتی بالا ایجاد کنید. هر جریان نشان دهنده یک بخش توزیع شده از نتایج است.

Change Streams از ویژگی‌های زیر پشتیبانی می‌کند:

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

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

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

برای مثال، نقش مدیر فهرست فروشگاه داده ( roles/datastore.indexAdmin ) این مجوزها را اعطا می‌کند.

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

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

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

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

    به پایگاه‌های داده بروید

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

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

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

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

    به پایگاه‌های داده بروید

  2. از لیست، یک Firestore با پایگاه داده سازگار با MongoDB انتخاب کنید. پنل Firestore Studio باز می‌شود.
  3. در پنل Explorer ، گره Change streams را پیدا کنید.
  4. برای باز یا بسته کردن گره، روی Toggle node کلیک کنید.

حذف جریان تغییر

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

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

    به پایگاه‌های داده بروید

  2. از لیست، یک Firestore با پایگاه داده سازگار با MongoDB انتخاب کنید. پنل Firestore Studio باز می‌شود.
  3. در پنل Explorer ، گره Change streams را پیدا کنید.
  4. برای باز یا بسته کردن گره، روی Toggle node کلیک کنید.
  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 از سر گرفته شود، از یک توکن resume استفاده کنید.

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

جریان‌های تغییر (Change Streams) از پنجره 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 برای تقسیم یک کوئری جریان تغییر بین چندین worker استفاده کنید. هر worker مسئول ارائه تغییرات برای مجموعه‌ای مجزا از اسناد است. شما باید از طریق runCommand یا یک query aggregate یک cursor موازی ایجاد کنید.

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

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

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

در این سناریو، رفتار 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: []
}

قدم بعدی چیست؟