راه‌اندازهای Cloud Firestore (نسل اول)

با Cloud Functions، می‌توانید رویدادها را در Cloud Firestore بدون نیاز به به‌روزرسانی کد کارخواه مدیریت کنید. می‌توانید تغییرات Cloud Firestore را ازطریق میانای تصویر فوری سند یا ازطریق Admin SDK اعمال کنید.

در چرخه عمر معمول، تابع Cloud Firestore کارهای زیر را انجام می‌دهد:

  1. منتظر تغییرات در سند خاصی می‌ماند.
  2. وقتی رویدادی رخ می‌دهد راه‌اندازی می‌شود و تکالیفش را انجام می‌دهد.
  3. شیء داده‌ای را دریافت می‌کند که حاوی عکس آنی از داده‌های ذخیره‌شده در سند مشخص‌شده است. برای رویدادهای نوشتن یا به‌روزرسانی، شیء داده حاوی دو نمای فوری است که وضعیت داده را قبل‌از و بعداز رویداد محرک نشان می‌دهد.

فاصله بین مکان نمونه Firestore و مکان تابع می‌تواند تأخیر قابل‌توجهی در شبکه ایجاد کند. برای بهینه‌سازی عملکرد، درصورت لزوم، مکان تابع را مشخص کنید.

راه‌اندازهای تابع Cloud Firestore

کیت توسعه نرم‌افزار Cloud Functions for Firebase شیء functions.firestore را صادر می‌کند که به شما امکان می‌دهد کارپردازهایی را ایجاد کنید که به رویدادهای خاص Cloud Firestore مرتبط هستند.

نوع رویداد ره‌انداز
onCreate وقتی سندی برای اولین‌بار نوشته می‌شود، راه‌اندازی می‌شود.
onUpdate وقتی سندی ازقبل وجود داشته باشد و مقدار آن تغییر کند، راه‌اندازی می‌شود.
onDelete وقتی سندی حاوی داده حذف می‌شود، راه‌اندازی می‌شود.
onWrite وقتی onCreate، onUpdate، یا onDelete راه‌اندازی شود، این ویژگی راه‌اندازی می‌شود.

اگر هنوز پروژه‌ای برای Cloud Functions for Firebase فعال نکرده‌اید، شروع به کار: نوشتن و استقرار اولین کارکردهای خود را بخوانید تا پروژه Cloud Functions for Firebase خود را پیکربندی و راه‌اندازی کنید.

نوشتن توابع راه‌اندازی‌شده Cloud Firestore

تعریف کردن راه‌انداز تابع

برای تعریف کردن راه‌انداز Cloud Firestore، مسیر سند و نوع رویداد را مشخص کنید:

Node.js

const functions = require('firebase-functions');

exports.myFunction = functions.firestore
  .document('my-collection/{docId}')
  .onWrite((change, context) => { /* ... */ });

مسیرهای سند می‌توانند به سند خاصی یا الگوی نویسه عام ارجاع دهند.

مشخص کردن یک سند

اگر می‌خواهید رویدادی را برای هر تغییری در سند خاصی راه‌اندازی کنید، می‌توانید از تابع زیر استفاده کنید.

Node.js

// Listen for any change on document `marie` in collection `users`
exports.myFunctionName = functions.firestore
    .document('users/marie').onWrite((change, context) => {
      // ... Your code here
    });

گروهی از اسناد را بااستفاده از کارت‌های جوکر مشخص کنید

اگر می‌خواهید محرکی را به گروهی از اسناد، مثلاً هر سندی در مجموعه‌ای خاص، پیوست کنید، به‌جای شناسه سند از {wildcard} استفاده کنید:

Node.js

// Listen for changes in all documents in the 'users' collection
exports.useWildcard = functions.firestore
    .document('users/{userId}')
    .onWrite((change, context) => {
      // If we set `/users/marie` to {name: "Marie"} then
      // context.params.userId == "marie"
      // ... and ...
      // change.after.data() == {name: "Marie"}
    });

در این مثال، وقتی هر فیلدی در هر سندی در users تغییر می‌کند، با کارت عامی به‌نام userId مطابقت می‌کند.

اگر سندی در users مجموعه‌های فرعی داشته باشد و فیلدی در یکی از اسناد آن مجموعه‌های فرعی تغییر کند، نویسه جانشین userId راه‌اندازی نمی‌شود.

مطابقت‌های کاراکتر عام از مسیر سند استخراج و در context.params ذخیره می‌شود. می‌توانید هر تعداد نویسه عام را که می‌خواهید تعریف کنید تا جایگزین شناسه‌های مجموعه یا سند صریح شود، برای مثال:

Node.js

// Listen for changes in all documents in the 'users' collection and all subcollections
exports.useMultipleWildcards = functions.firestore
    .document('users/{userId}/{messageCollectionId}/{messageId}')
    .onWrite((change, context) => {
      // If we set `/users/marie/incoming_messages/134` to {body: "Hello"} then
      // context.params.userId == "marie";
      // context.params.messageCollectionId == "incoming_messages";
      // context.params.messageId == "134";
      // ... and ...
      // change.after.data() == {body: "Hello"}
    });

راه‌اندازهای رویداد

وقتی سند جدیدی ایجاد می‌شود، تابعی را راه‌اندازی کنید

بااستفاده از مدیریت‌کننده onCreate() با کارت عام می‌توانید تابعی را راه‌اندازی کنید تا هرزمان سند جدیدی در مجموعه‌ای ایجاد شد اجرا شود. این تابع نمونه هر بار که نمایه کاربر جدیدی اضافه می‌شود createUser را فرا می‌خواند:

Node.js

exports.createUser = functions.firestore
    .document('users/{userId}')
    .onCreate((snap, context) => {
      // Get an object representing the document
      // e.g. {'name': 'Marie', 'age': 66}
      const newValue = snap.data();

      // access a particular field as you would any JS property
      const name = newValue.name;

      // perform desired operations ...
    });

وقتی سندی به‌روز می‌شود، تابعی را راه‌اندازی کنید

همچنین می‌توانید تابعی را راه‌اندازی کنید تا وقتی سندی بااستفاده از تابع onUpdate() با کارت جوکر به‌روزرسانی می‌شود اجرا شود. این تابع نمونه درصورتی updateUser را فرا می‌خواند که کاربر نمایه‌اش را تغییر دهد:

Node.js

exports.updateUser = functions.firestore
    .document('users/{userId}')
    .onUpdate((change, context) => {
      // Get an object representing the document
      // e.g. {'name': 'Marie', 'age': 66}
      const newValue = change.after.data();

      // ...or the previous value before this update
      const previousValue = change.before.data();

      // access a particular field as you would any JS property
      const name = newValue.name;

      // perform desired operations ...
    });

وقتی سندی حذف می‌شود، تابعی را راه‌اندازی کنید

همچنین می‌توانید بااستفاده از تابع onDelete() با کارت عام، تابعی را هنگام حذف سند راه‌اندازی کنید. این مثال وقتی کاربر نمایه کاربری‌اش را حذف می‌کند، تابع deleteUser را فرا می‌خواند:

Node.js

exports.deleteUser = functions.firestore
    .document('users/{userID}')
    .onDelete((snap, context) => {
      // Get an object representing the document prior to deletion
      // e.g. {'name': 'Marie', 'age': 66}
      const deletedValue = snap.data();

      // perform desired operations ...
    });

راه‌اندازی تابع برای همه تغییرات سند

اگر نوع رویدادی که راه‌اندازی می‌شود برایتان مهم نیست، می‌توانید بااستفاده از تابع onWrite() با کارت عام، به همه تغییرات در سند Cloud Firestore گوش دهید. این تابع نمونه modifyUser را اگر کاربری ایجاد، به‌روزرسانی، یا حذف شود فراخوانی می‌کند:

Node.js

exports.modifyUser = functions.firestore
    .document('users/{userID}')
    .onWrite((change, context) => {
      // Get an object with the current document value.
      // If the document does not exist, it has been deleted.
      const document = change.after.exists ? change.after.data() : null;

      // Get an object with the previous document value (for update or delete)
      const oldDocument = change.before.data();

      // perform desired operations ...
    });

خواندن و نوشتن داده‌ها

وقتی تابعی راه‌اندازی می‌شود، نمای لحظه‌ای از داده‌های مربوط به رویداد ارائه می‌دهد. می‌توانید از این نمای فوری برای خواندن یا نوشتن در سندی که رویداد را راه‌اندازی کرده است استفاده کنید، یا از Firebase Admin SDK برای دسترسی به بخش‌های دیگر پایگاه داده‌تان استفاده کنید.

داده‌های رویداد

خواندن داده‌ها

وقتی تابعی راه‌اندازی می‌شود، ممکن است بخواهید داده‌های سندی را که به‌روز شده است دریافت کنید یا داده‌های قبل‌از به‌روزرسانی را دریافت کنید. بااستفاده از change.before.data() که حاوی تصویر فوری سند قبل‌از به‌روزرسانی است، می‌توانید داده‌های قبلی را دریافت کنید. به‌همین ترتیب، change.after.data() حاوی وضعیت لحظه‌ای سند پس‌از به‌روزرسانی است.

Node.js

exports.updateUser2 = functions.firestore
    .document('users/{userId}')
    .onUpdate((change, context) => {
      // Get an object representing the current document
      const newValue = change.after.data();

      // ...or the previous value before this update
      const previousValue = change.before.data();
    });

می‌توانید به دارایی‌ها همان‌گونه که در هر شیء دیگری دسترسی دارید دسترسی داشته باشید. یا اینکه می‌توانید از تابع get برای دسترسی به فیلدهای خاص استفاده کنید:

Node.js

// Fetch data using standard accessors
const age = snap.data().age;
const name = snap.data()['name'];

// Fetch data using built in accessor
const experience = snap.get('experience');

نوشتن داده‌ها

هر فراخوانی تابع با سند خاصی در پایگاه داده Cloud Firestore شما مرتبط است. می‌توانید به‌عنوان DocumentReference در دارایی ref از نمای لحظه‌ای که به تابع شما برگردانده شده است به آن سند دسترسی داشته باشید.

این DocumentReference از کیت توسعه نرم‌افزار Cloud Firestore Node.js می‌آید و شامل روش‌هایی مثل update()، set()، و remove() است تا بتوانید به‌راحتی سندی را که تابع را راه‌اندازی کرده است اصلاح کنید.

Node.js

// Listen for updates to any `user` document.
exports.countNameChanges = functions.firestore
    .document('users/{userId}')
    .onUpdate((change, context) => {
      // Retrieve the current and previous value
      const data = change.after.data();
      const previousData = change.before.data();

      // We'll only update if the name has changed.
      // This is crucial to prevent infinite loops.
      if (data.name == previousData.name) {
        return null;
      }

      // Retrieve the current count of name changes
      let count = data.name_change_count;
      if (!count) {
        count = 0;
      }

      // Then return a promise of a set operation to update the count
      return change.after.ref.set({
        name_change_count: count + 1
      }, {merge: true});
    });

داده‌های خارج از رویداد راه‌انداز

Cloud Functions در محیطی مطمئن اجرا می‌شود، به این معنی که به‌عنوان حساب سرویس در پروژه شما مجاز است. می‌توانید بااستفاده از Firebase Admin SDK، خواندن و نوشتن انجام دهید:

Node.js

const admin = require('firebase-admin');
admin.initializeApp();

const db = admin.firestore();

exports.writeToFirestore = functions.firestore
  .document('some/doc')
  .onWrite((change, context) => {
    db.doc('some/otherdoc').set({ ... });
  });

محدودیت‌ها

محدودیت‌های زیر را برای Cloud Firestore راه‌انداز برای Cloud Functions درنظر داشته باشید:

  • پیش‌نیاز Cloud Functions (نسل اول) پایگاه داده «(پیش‌فرض)» موجود در حالت بومی Firestore است. از پایگاه‌های داده نام‌گذاری‌شده Cloud Firestore یا حالت Datastore پشتیبانی نمی‌کند. لطفاً از Cloud Functions (نسل دوم) برای پیکربندی رویدادها در چنین مواردی استفاده کنید.
  • راه‌اندازی بین پروژه‌ای با Cloud Functions و Cloud Firestore محرک محدودیت است. برای راه‌اندازی Cloud Firestore راه‌انداز، Cloud Functions باید در همان پروژه باشد.
  • ترتیب تضمین نمی‌شود. تغییرات سریع می‌تواند فراخوانی‌های تابع را در ترتیبی غیرمنتظره فعال کند.
  • رویدادها حداقل یک‌بار ارائه می‌شوند، اما یک رویداد ممکن است منجر به چندین فراخوانی تابع شود. از اتکا به سازوکارهای دقیقاً یک‌بار پرهیز کنید و توابع خودتوان بنویسید.
  • Cloud Firestore در حالت Datastore به Cloud Functions (نسل دوم) نیاز دارد. ‫Cloud Functions (نسل اول) از حالت Datastore پشتیبانی نمی‌کند.
  • راه‌انداز با یک پایگاه داده واحد مرتبط است. نمی‌توانید محرکی ایجاد کنید که با چندین پایگاه داده مطابقت داشته باشد.
  • حذف پایگاه داده به‌طور خودکار باعث حذف هیچ‌یک از محرک‌های آن پایگاه داده نمی‌شود. راه‌انداز ارسال رویدادها را متوقف می‌کند اما تا زمانی که راه‌انداز را حذف کنید همچنان وجود دارد.
  • اگر رویداد منطبق از حداکثر اندازه درخواست فراتر رود، ممکن است رویداد به Cloud Functions (نسل اول) تحویل داده نشود.
    • رویدادهایی که به‌دلیل اندازه درخواست تحویل داده نشده‌اند در گزارش‌های پلاتفرم ثبت می‌شوند و در شمارش استفاده از گزارش برای پروژه لحاظ می‌شوند.
    • می‌توانید این گزارش‌ها را در «کاوشگر گزارش‌ها» با پیام «رویداد نمی‌تواند به تابع Cloud تحویل داده شود زیرا اندازه از حد مجاز برای نسل اول فراتر رفته است…» با شدت error پیدا کنید. می‌توانید نام تابع را در فیلد functionName پیدا کنید. اگر فیلد receiveTimestamp هنوز در یک ساعت آینده است، می‌توانید با خواندن سند موردنظر با یک عکس آنی قبل و بعداز مُهر زمان، محتوای رویداد واقعی را استنباط کنید.
    • برای جلوگیری از چنین آهنگ کلامی، می‌توانید:
      • انتقال و ارتقا به Cloud Functions (نسل دوم)
      • کوچک کردن سند
      • حذف Cloud Functions مورد بحث
    • می‌توانید خود گزارش‌گیری را بااستفاده از استثناها خاموش کنید اما توجه داشته باشید که رویدادهای تخلف‌آمیز همچنان ارائه نخواهند شد.