Check out what’s new from Firebase at Google I/O 2022. Learn more

محرک های پایگاه داده

با توابع Cloud، می‌توانید رویدادها را در پایگاه داده بیدرنگ Firebase بدون نیاز به به‌روزرسانی کد مشتری مدیریت کنید. Cloud Functions به شما امکان می دهد عملیات پایگاه داده بیدرنگ را با امتیازات مدیریتی کامل اجرا کنید و تضمین می کند که هر تغییر در پایگاه داده بیدرنگ به صورت جداگانه پردازش می شود. می‌توانید از طریق DataSnapshot یا از طریق Admin SDK تغییراتی در پایگاه داده بیدرنگ Firebase ایجاد کنید.

در یک چرخه عمر معمولی، یک تابع پایگاه داده بیدرنگ Firebase کارهای زیر را انجام می دهد:

  1. منتظر تغییرات در یک مکان خاص پایگاه داده بیدرنگ است.
  2. هنگامی که یک رویداد رخ می دهد و وظایف خود را انجام می دهد، فعال می شود (برای نمونه هایی از موارد استفاده، به «چه کاری می توانم با توابع ابری انجام دهم؟» مراجعه کنید.
  3. یک شی داده را دریافت می کند که حاوی یک عکس فوری از داده های ذخیره شده در سند مشخص شده است.

یک تابع پایگاه داده بیدرنگ را فعال کنید

توابع جدید برای رویدادهای پایگاه داده بیدرنگ با functions.database ایجاد کنید. برای کنترل زمان راه‌اندازی تابع، یکی از کنترل‌کننده‌های رویداد را مشخص کنید و مسیر پایگاه داده بیدرنگ را که در آن به رویدادها گوش می‌دهد، مشخص کنید.

کنترل کننده رویداد را تنظیم کنید

توابع به شما امکان می دهند رویدادهای پایگاه داده بیدرنگ را در دو سطح از ویژگی مدیریت کنید. شما می توانید به طور خاص فقط برای رویدادهای ایجاد، به روز رسانی یا حذف گوش دهید، یا می توانید برای هر نوع تغییر در یک مسیر گوش دهید. Cloud Functions از این دسته رویدادها برای پایگاه داده بیدرنگ پشتیبانی می کند:

  • onWrite() که هنگام ایجاد، به‌روزرسانی یا حذف داده‌ها در پایگاه داده بیدرنگ فعال می‌شود.
  • onCreate() که با ایجاد داده های جدید در پایگاه داده بیدرنگ فعال می شود.
  • onUpdate() که با به روز رسانی داده ها در پایگاه داده بیدرنگ فعال می شود.
  • onDelete() که هنگام حذف داده ها از پایگاه داده بیدرنگ فعال می شود.

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

برای کنترل زمان و مکانی که تابع شما باید فعال شود، ref(path) را برای تعیین یک مسیر فراخوانی کنید و به صورت اختیاری یک نمونه پایگاه داده بیدرنگ را با instance('INSTANCE_NAME') مشخص کنید. اگر نمونه ای را مشخص نکنید، تابع به نمونه پیش فرض پایگاه داده بیدرنگ برای پروژه Firebase مستقر می شود، به عنوان مثال:

  • نمونه پیش‌فرض پایگاه داده بیدرنگ: functions.database.ref('/foo/bar')
  • نمونه با نام "my-app-db-2": functions.database.instance('my-app-db-2').ref('/foo/bar')

این روش‌ها تابع شما را هدایت می‌کنند تا نوشته‌ها را در یک مسیر خاص در نمونه پایگاه داده Realtime مدیریت کند. مشخصات مسیر با تمام نوشته هایی که یک مسیر را لمس می کنند، از جمله نوشته هایی که در هر نقطه زیر آن اتفاق می افتد، مطابقت دارد. اگر مسیر تابع خود را به عنوان /foo/bar تنظیم کنید، با رویدادهای هر دوی این مکان ها مطابقت دارد:

 /foo/bar
 /foo/bar/baz/really/deep/path

در هر صورت، Firebase تفسیر می کند که رویداد در /foo/bar رخ می دهد، و داده رویداد شامل داده های قدیمی و جدید در /foo/bar است. اگر داده های رویداد ممکن است بزرگ باشند، به جای استفاده از یک تابع منفرد در نزدیکی ریشه پایگاه داده خود، از چندین تابع در مسیرهای عمیق تر استفاده کنید. برای بهترین عملکرد، فقط داده ها را در عمیق ترین سطح ممکن درخواست کنید.

می‌توانید با احاطه کردن آن با براکت‌های فرفری، یک جزء مسیر را به‌عنوان علامت عام مشخص کنید. ref('foo/{bar}') با هر فرزند /foo مطابقت دارد. مقادیر این مولفه‌های مسیر حروف عام در شیء EventContext.params تابع شما موجود است. در این مثال، مقدار به صورت context.params.bar در دسترس است.

مسیرهای دارای حروف عام می‌توانند چندین رویداد را از یک نوشتن منفرد مطابقت دهند. یک درج از

{
  "foo": {
    "hello": "world",
    "firebase": "functions"
  }
}

مسیر "/foo/{bar}" را دو بار تطبیق می دهد: یک بار با "hello": "world" و دوباره با "firebase": "functions" .

مدیریت داده های رویداد

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

در این مثال، تابع عکس فوری را برای مسیر مشخص شده به عنوان snap بازیابی می کند، رشته را در آن مکان به حروف بزرگ تبدیل می کند و رشته تغییر یافته را در پایگاه داده می نویسد:

// Listens for new messages added to /messages/:pushId/original and creates an
// uppercase version of the message to /messages/:pushId/uppercase
exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
    .onCreate((snapshot, context) => {
      // Grab the current value of what was written to the Realtime Database.
      const original = snapshot.val();
      functions.logger.log('Uppercasing', context.params.pushId, original);
      const uppercase = original.toUpperCase();
      // You must return a Promise when performing asynchronous tasks inside a Functions such as
      // writing to the Firebase Realtime Database.
      // Setting an "uppercase" sibling in the Realtime Database returns a Promise.
      return snapshot.ref.parent.child('uppercase').set(uppercase);
    });

دسترسی به اطلاعات احراز هویت کاربر

از EventContext.auth و EventContext.authType ، می توانید به اطلاعات کاربر، از جمله مجوزها، برای کاربری که یک تابع را راه اندازی کرده است، دسترسی داشته باشید. این می تواند برای اجرای قوانین امنیتی مفید باشد و به عملکرد شما اجازه می دهد تا عملیات های مختلف را بر اساس سطح مجوزهای کاربر انجام دهد:

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

exports.simpleDbFunction = functions.database.ref('/path')
    .onCreate((snap, context) => {
      if (context.authType === 'ADMIN') {
        // do something
      } else if (context.authType === 'USER') {
        console.log(snap.val(), 'written by', context.auth.uid);
      }
    });

همچنین، می توانید از اطلاعات احراز هویت کاربر برای "جعل هویت" یک کاربر و انجام عملیات نوشتن از طرف کاربر استفاده کنید. برای جلوگیری از مشکلات همزمانی، حتماً نمونه برنامه را همانطور که در زیر نشان داده شده است حذف کنید:

exports.impersonateMakeUpperCase = functions.database.ref('/messages/{pushId}/original')
    .onCreate((snap, context) => {
      const appOptions = JSON.parse(process.env.FIREBASE_CONFIG);
      appOptions.databaseAuthVariableOverride = context.auth;
      const app = admin.initializeApp(appOptions, 'app');
      const uppercase = snap.val().toUpperCase();
      const ref = snap.ref.parent.child('uppercase');

      const deleteApp = () => app.delete().catch(() => null);

      return app.database().ref(ref).set(uppercase).then(res => {
        // Deleting the app is necessary for preventing concurrency leaks
        return deleteApp().then(() => res);
      }).catch(err => {
        return deleteApp().then(() => Promise.reject(err));
      });
    });

خواندن مقدار قبلی

شی Change دارای یک خاصیت before است که به شما امکان می دهد آنچه را که قبل از رویداد در پایگاه داده Realtime ذخیره شده است بررسی کنید. ویژگی Before یک DataSnapshot before برمی‌گرداند که در آن همه متدها (مثلاً val() و exists() ) به مقدار قبلی اشاره می‌کنند. می توانید مقدار جدید را با استفاده از DataSnapshot اصلی یا خواندن ویژگی after بخوانید. این ویژگی در هر Change ، DataSnapshot دیگری است که وضعیت داده ها را پس از وقوع رویداد نشان می دهد.

به عنوان مثال، می‌توان before ویژگی Before استفاده کرد تا مطمئن شویم که این تابع زمانی که برای اولین بار ایجاد می‌شود، متن را فقط با حروف بزرگ می‌نویسد:

exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
    .onWrite((change, context) => {
      // Only edit data when it is first created.
      if (change.before.exists()) {
        return null;
      }
      // Exit when the data is deleted.
      if (!change.after.exists()) {
        return null;
      }
      // Grab the current value of what was written to the Realtime Database.
      const original = change.after.val();
      console.log('Uppercasing', context.params.pushId, original);
      const uppercase = original.toUpperCase();
      // You must return a Promise when performing asynchronous tasks inside a Functions such as
      // writing to the Firebase Realtime Database.
      // Setting an "uppercase" sibling in the Realtime Database returns a Promise.
      return change.after.ref.parent.child('uppercase').set(uppercase);
    });