Cloud Firestore را با توابع Cloud گسترش دهید

با Cloud Functions ، می‌توانید کد Node.js را برای مدیریت رویدادهایی که توسط تغییرات در پایگاه داده Cloud Firestore ایجاد می‌شوند، مستقر کنید. این به شما امکان می دهد تا به راحتی عملکرد سمت سرور را بدون اجرای سرورهای خود به برنامه خود اضافه کنید.

برای نمونه‌هایی از موارد استفاده، به «چه کاری می‌توانم با Cloud Functions کنم» مراجعه کنید؟ یا مخزن Functions Samples GitHub.

عملکرد Cloud Firestore فعال می شود

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

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

اگر هنوز پروژه‌ای را برای Cloud Functions for Firebase فعال نکرده‌اید، شروع کنید: Write and Deploy Your First Functions را بخوانید تا پروژه 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 SDK می‌آید و شامل متدهایی مانند 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 Firestore در حالت Datastore به Cloud Functions (نسل دوم) نیاز دارد. Cloud Functions (نسل اول) از حالت Datastore پشتیبانی نمی کند.
  • یک ماشه با یک پایگاه داده واحد مرتبط است. شما نمی توانید تریگری ایجاد کنید که با چندین پایگاه داده مطابقت داشته باشد.
  • حذف یک پایگاه داده به طور خودکار هیچ عاملی را برای آن پایگاه داده حذف نمی کند. ماشه تحویل رویدادها را متوقف می کند اما تا زمانی که ماشه را حذف نکنید به وجود خود ادامه می دهد.
  • اگر یک رویداد منطبق از حداکثر اندازه درخواست بیشتر شود، ممکن است رویداد به Cloud Functions (نسل اول) تحویل داده نشود.
    • رویدادهایی که به دلیل اندازه درخواست تحویل نمی‌شوند، در گزارش‌های پلتفرم ثبت می‌شوند و به‌حساب استفاده از گزارش برای پروژه حساب می‌شوند.
    • می‌توانید این گزارش‌ها را در کاوشگر گزارش‌ها با پیام شدت error پیدا کنید "رویداد نمی‌تواند به عملکرد Cloud تحویل داده شود به دلیل اندازه بیش از حد مجاز برای نسل اول...". می توانید نام تابع را در قسمت functionName پیدا کنید. اگر قسمت receiveTimestamp هنوز تا یک ساعت دیگر باقی مانده است، می توانید با خواندن سند مورد نظر با یک عکس فوری قبل و بعد از مهر زمانی، محتوای واقعی رویداد را استنباط کنید.
    • برای جلوگیری از چنین آهنگی، می توانید:
      • مهاجرت و ارتقاء به Cloud Functions (نسل دوم)
      • سند را کوچک کنید
      • Cloud Functions مورد نظر را حذف کنید
    • شما می توانید خود گزارش را با استفاده از استثناها خاموش کنید، اما توجه داشته باشید که رویدادهای توهین آمیز هنوز تحویل داده نمی شوند.