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

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

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

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

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

محرک‌های تابع Cloud Firestore

Cloud Functions for Firebase SDK یک شیء functions.firestore صادر می‌کند که به شما امکان می‌دهد هندلرهایی مرتبط با رویدادهای خاص Cloud Firestore ایجاد کنید.

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

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

نوشتن توابع فعال شده توسط Cloud Firestore

تعریف یک تریگر تابع

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

نود جی اس

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

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

مسیرهای سند می‌توانند به یک سند خاص یا یک الگوی wildcard اشاره کنند.

یک سند واحد را مشخص کنید

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

نود جی اس

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

مشخص کردن گروهی از اسناد با استفاده از کاراکترهای عمومی (wildcards)

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

نود جی اس

// 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 تغییر می‌کند، با یک wildcard به نام userId مطابقت پیدا می‌کند.

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

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

نود جی اس

// 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() به همراه یک wildcard، یک تابع را برای اجرا فعال کنید. این تابع مثال، هر بار که یک پروفایل کاربری جدید اضافه می‌شود، createUser فراخوانی می‌کند:

نود جی اس

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() و یک wildcard ، هنگام به‌روزرسانی یک سند، تابعی را فعال کنید. این تابع مثال، در صورت تغییر پروفایل کاربر، updateUser فراخوانی می‌کند:

نود جی اس

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() به همراه یک wildcard ، یک تابع را فعال کنید. این تابع مثال، هنگامی که یک کاربر پروفایل کاربری خود را حذف می‌کند، deleteUser فراخوانی می‌کند:

نود جی اس

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() به همراه یک wildcard ، به تمام تغییرات در یک سند Cloud Firestore گوش دهید. این تابع مثال، در صورت ایجاد، به‌روزرسانی یا حذف کاربر، modifyUser فراخوانی می‌کند:

نود جی اس

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() شامل وضعیت عکس فوری سند بعد از به‌روزرسانی است.

نود جی اس

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 برای دسترسی به فیلدهای خاص استفاده کنید:

نود جی اس

// 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 از snapshot برگردانده شده به تابع خود دسترسی داشته باشید.

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

نود جی اس

// 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 عملیات خواندن و نوشتن را انجام دهید:

نود جی اس

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 توجه کنید:

  • Cloud Functions (نسل اول) در حالت بومی Firestore، یک پایگاه داده "(پیش‌فرض)" موجود را پیش‌نیاز دارد. این قابلیت از پایگاه‌های داده با نام Cloud Firestore یا حالت Datastore پشتیبانی نمی‌کند. لطفاً در چنین مواردی Cloud Functions (نسل دوم) برای پیکربندی رویدادها استفاده کنید.
  • راه‌اندازی بین پروژه‌ای با Cloud Functions و Cloud Firestore trigger یک محدودیت است. برای راه‌اندازی Cloud Firestore trigger، Cloud Functions باید در یک پروژه باشند.
  • ترتیب اجرا تضمین شده نیست. تغییرات سریع می‌توانند باعث فراخوانی توابع با ترتیب غیرمنتظره شوند.
  • رویدادها حداقل یک بار اجرا می‌شوند، اما یک رویداد واحد ممکن است منجر به فراخوانی چندین تابع شود. از تکیه بر مکانیزم‌های دقیقاً یک‌باره خودداری کنید و توابع خودتوان بنویسید.
  • Cloud Firestore در حالت Datastore به Cloud Functions (نسل دوم) نیاز دارد. Cloud Functions (نسل اول) از حالت Datastore پشتیبانی نمی‌کند.
  • یک تریگر (Trigger) به یک پایگاه داده واحد مرتبط است. شما نمی‌توانید تریگری ایجاد کنید که با چندین پایگاه داده مطابقت داشته باشد.
  • حذف یک پایگاه داده به طور خودکار هیچ تریگر (triggers) را برای آن پایگاه داده حذف نمی‌کند. تریگر ارائه رویدادها را متوقف می‌کند اما تا زمانی که تریگر را حذف نکنید، همچنان وجود خواهد داشت.
  • اگر یک رویداد منطبق از حداکثر اندازه درخواست فراتر رود، ممکن است رویداد به Cloud Functions (نسل اول) تحویل داده نشود.
    • رویدادهایی که به دلیل حجم درخواست تحویل داده نمی‌شوند، در لاگ‌های پلتفرم ثبت می‌شوند و در میزان استفاده از لاگ برای پروژه محاسبه می‌شوند.
    • می‌توانید این گزارش‌ها را در Logs Explorer با پیام "Event cannot deliver to Cloud function due to size exceeding the limit for 1st gen..." از نظر شدت error پیدا کنید. می‌توانید نام تابع را در فیلد functionName پیدا کنید. اگر فیلد receiveTimestamp هنوز تا یک ساعت دیگر باقی مانده باشد، می‌توانید با خواندن سند مورد نظر به همراه یک snapshot قبل و بعد از برچسب زمانی، محتوای واقعی رویداد را استنباط کنید.
    • برای جلوگیری از چنین ریتمی، می‌توانید:
      • مهاجرت و ارتقاء به Cloud Functions (نسل دوم)
      • کوچک کردن حجم سند
      • Cloud Functions مورد نظر را حذف کنید
    • شما می‌توانید با استفاده از استثنائات، خودِ ثبت وقایع را غیرفعال کنید، اما توجه داشته باشید که رویدادهای مشکل‌ساز همچنان اجرا نخواهند شد.