راه‌اندازی پایگاه داده بیدرنگ

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

در یک چرخه حیات معمولی، یک تابع Firebase Realtime Database موارد زیر را انجام می‌دهد:

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

شما می‌توانید در پاسخ به نوشتن، ایجاد، به‌روزرسانی یا حذف گره‌های پایگاه داده در Firebase Realtime Database یک تابع را فعال کنید. برای کنترل زمان فعال شدن تابع، یکی از کنترل‌کننده‌های رویداد را مشخص کنید و مسیر Realtime Database را که در آن به رویدادها گوش می‌دهد، مشخص کنید.

تنظیم محل تابع

فاصله بین محل قرارگیری یک نمونه Realtime Database و محل قرارگیری تابع می‌تواند تأخیر قابل توجهی در شبکه ایجاد کند. همچنین، عدم تطابق بین مناطق می‌تواند منجر به شکست در استقرار شود. برای جلوگیری از این موقعیت‌ها، محل تابع را طوری مشخص کنید که با محل قرارگیری نمونه پایگاه داده مطابقت داشته باشد.

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

توابع به شما امکان می‌دهند رویدادهای Realtime Database را در دو سطح از دقت مدیریت کنید؛ می‌توانید به طور خاص فقط به رویدادهای نوشتن، ایجاد، به‌روزرسانی یا حذف گوش دهید، یا می‌توانید به هرگونه تغییر از هر نوع در یک مرجع گوش دهید.

این هندلرها برای پاسخ به رویدادهای Realtime Database در دسترس هستند:

نود جی اس

  • onValueWritten() ‎ زمانی که داده‌ها در Realtime Database ایجاد، به‌روزرسانی یا حذف می‌شوند، فعال می‌شود.
  • onValueCreated() ‎ فقط زمانی فعال می‌شود که داده‌ها در Realtime Database ایجاد شوند.
  • onValueUpdated() ‎ فقط زمانی اجرا می‌شود که داده‌ها در Realtime Database به‌روزرسانی شوند.
  • onValueDeleted() ‎ فقط زمانی اجرا می‌شود که داده‌ها در Realtime Database حذف شوند.

پایتون

  • on_value_written() ‎ زمانی که داده‌ها در Realtime Database ایجاد، به‌روزرسانی یا حذف می‌شوند، فعال می‌شود.
  • on_value_created() ‎ فقط زمانی فعال می‌شود که داده‌ها در Realtime Database ایجاد شوند.
  • on_value_updated() ‎ فقط زمانی اجرا می‌شود که داده‌ها در Realtime Database به‌روزرسانی شوند.
  • on_value_deleted() ‎ فقط زمانی اجرا می‌شود که داده‌ها در Realtime Database حذف شوند.

ماژول‌های مورد نیاز را وارد کنید

در سورس تابع خود، باید ماژول‌های SDK مورد نظر خود را وارد کنید. برای این نمونه، لازم است ماژول‌های HTTP و Realtime Database را به همراه ماژول Firebase Admin SDK برای نوشتن در Realtime Database وارد کنید.

نود جی اس

// The Cloud Functions for Firebase SDK to setup triggers and logging.
const {onRequest} = require("firebase-functions/https");
const {onValueCreated} = require("firebase-functions/database");
const {logger} = require("firebase-functions");

// The Firebase Admin SDK to access the Firebase Realtime Database.
const admin = require("firebase-admin");
admin.initializeApp();

پایتون

# The Cloud Functions for Firebase SDK to create Cloud Functions and set up triggers.
from firebase_functions import db_fn, https_fn

# The Firebase Admin SDK to access the Firebase Realtime Database.
from firebase_admin import initialize_app, db

app = initialize_app()

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

برای کنترل زمان و مکان اجرای تابع، آن را با یک مسیر و در صورت تمایل یک نمونه Realtime Database پیکربندی کنید. اگر نمونه‌ای مشخص نکنید، تابع به تمام نمونه‌های Realtime Database در ناحیه تابع گوش می‌دهد. همچنین می‌توانید یک الگوی نمونه Realtime Database برای استقرار در زیرمجموعه‌ای انتخابی از نمونه‌ها در همان ناحیه مشخص کنید.

برای مثال:

نود جی اس

// All Realtime Database instances in default function region us-central1 at path "/user/{uid}"
// There must be at least one Realtime Database present in us-central1.
const onWrittenFunctionDefault = onValueWritten("/user/{uid}", (event) => {
  // …
});

// Instance named "my-app-db-2", at path "/user/{uid}".
// The "my-app-db-2" instance must exist in this region.
const OnWrittenFunctionInstance = onValueWritten(
  {
    ref: "/user/{uid}",
    instance: "my-app-db-2"
    // This example assumes us-central1, but to set location:
    // region: "europe-west1"
  },
  (event) => {
    // …
  }
);

// Instance with "my-app-db-" prefix, at path "/user/{uid}", where uid ends with @gmail.com.
// There must be at least one Realtime Database with "my-app-db-*" prefix in this region.
const onWrittenFunctionInstance = onValueWritten(
  {
    ref: "/user/{uid=*@gmail.com}",
    instance: "my-app-db-*"
    // This example assumes us-central1, but to set location:
    // region: "europe-west1"
  },
  (event) => {
    // …
  }
);

پایتون

# All Realtime Database instances in default function region us-central1 at path "/user/{uid}"
# There must be at least one Realtime Database present in us-central1.
@db_fn.on_value_written(r"/user/{uid}")
def onwrittenfunctiondefault(event: db_fn.Event[db_fn.Change]):
    # ...
    pass

# Instance named "my-app-db-2", at path "/user/{uid}".
# The "my-app-db-2" instance must exist in this region.
@db_fn.on_value_written(
    reference=r"/user/{uid}",
    instance="my-app-db-2",
    # This example assumes us-central1, but to set location:
    # region="europe-west1",
)
def on_written_function_instance(event: db_fn.Event[db_fn.Change]):
    # ...
    pass

# Instance with "my-app-db-" prefix, at path "/user/{uid}", where uid ends with @gmail.com.
# There must be at least one Realtime Database with "my-app-db-*" prefix in this region.
@db_fn.on_value_written(
    reference=r"/user/{uid=*@gmail.com}",
    instance="my-app-db-*",
    # This example assumes us-central1, but to set location:
    # region="europe-west1",
)
def on_written_function_instance(event: db_fn.Event[db_fn.Change]):
    # ...
    pass

این پارامترها تابع شما را هدایت می‌کنند تا نوشتن‌ها را در یک مسیر خاص در نمونه Realtime Database مدیریت کند.

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

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

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

وایلدکاردینگ و کپچرینگ

می‌توانید از {key} ، {key=*} ، {key=prefix*} ، {key=*suffix} برای ثبت استفاده کنید. * ، prefix* ، *suffix برای wildcarding تک قسمتی است. توجه: ** نشان‌دهنده wildcarding چند قسمتی است که Realtime Database از آن پشتیبانی نمی‌کند. به بخش «درک الگوهای مسیر» مراجعه کنید.

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

  • با استفاده از ستاره، * . برای مثال، foo/* با هر فرزندی که یک سطح از سلسله مراتب گره زیر foo/ باشد، مطابقت دارد.
  • استفاده از سگمنتی که دقیقاً شامل ستاره * باشد. برای مثال، foo/app*-us با هر سگمنت فرزندی که زیر foo/ با پیشوند app و پسوند -us باشد، مطابقت دارد.

مسیرهای دارای wildcard می‌توانند چندین رویداد را از، مثلاً یک write واحد، مطابقت دهند. درجِ

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

مسیر "/foo/*" را دو بار تطبیق می‌دهد: یک بار با "hello": "world" و بار دیگر با "firebase": "functions" .

ثبت مسیر. می‌توانید تطابق‌های مسیر را در متغیرهای نامگذاری‌شده ثبت کنید تا در کد تابع خود استفاده کنید (مثلاً /user/{uid} ، /user/{uid=*-us} ).

مقادیر متغیرهای ضبط‌شده در شیء database.DatabaseEvent.params تابع شما موجود است.

wildcarding نمونه. همچنین می‌توانید یک کامپوننت نمونه را با استفاده از wildcarding مشخص کنید. یک wildcard نمونه می‌تواند پیشوند، پسوند یا هر دو را داشته باشد (مثلاً my-app-*-prod ).

مرجع Wildcard و Capture

با استفاده از Cloud Functions (نسل دوم) و Realtime Database ، می‌توان هنگام تعیین ref و instance از یک الگو استفاده کرد. هر رابط تریگر گزینه‌های زیر را برای تعیین محدوده یک تابع خواهد داشت:

مشخص کردن ref مشخص کردن instance رفتار
تکی ( /foo/bar ) مشخص نکردن کنترل‌کننده‌ی دامنه‌ها برای تمام نمونه‌های موجود در ناحیه‌ی تابع.
تکی ( /foo/bar ) مجرد ( 'my-new-db' ) کنترل‌کننده‌ی دامنه‌ها (scope handler) برای نمونه‌ی خاص در ناحیه‌ی تابع.
تکی ( /foo/bar ) الگو ( 'inst-prefix*' ) کنترل‌کننده‌ی دامنه‌ها (scope handler) برای تمام نمونه‌هایی که با الگو در ناحیه‌ی تابع مطابقت دارند.
الگو ( /foo/{bar} ) مشخص نکردن کنترل‌کننده‌ی دامنه‌ها برای تمام نمونه‌های موجود در ناحیه‌ی تابع.
الگو ( /foo/{bar} ) مجرد ( 'my-new-db' ) کنترل‌کننده‌ی دامنه‌ها (scope handler) برای نمونه‌ی خاص در ناحیه‌ی تابع.
الگو ( /foo/{bar} ) الگو ( 'inst-prefix*' ) کنترل‌کننده‌ی دامنه‌ها (scope handler) برای تمام نمونه‌هایی که با الگو در ناحیه‌ی تابع مطابقت دارند.

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

وقتی یک رویداد Realtime Database آغاز می‌شود، یک شیء Event به تابع handler شما منتقل می‌کند. این شیء دارای یک ویژگی data است که برای رویدادهای ایجاد و حذف، شامل یک snapshot از داده‌های ایجاد شده یا حذف شده است.

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

نود جی اس

// Listens for new messages added to /messages/:pushId/original and creates an
// uppercase version of the message to /messages/:pushId/uppercase
// for all databases in 'us-central1'
exports.makeuppercase = onValueCreated(
    "/messages/{pushId}/original",
    (event) => {
    // Grab the current value of what was written to the Realtime Database.
      const original = event.data.val();
      logger.log("Uppercasing", event.params.pushId, original);
      const uppercase = original.toUpperCase();
      // You must return a Promise when performing
      // asynchronous tasks inside a function, such as
      // writing to the Firebase Realtime Database.
      // Setting an "uppercase" sibling in the
      // Realtime Database returns a Promise.
      return event.data.ref.parent.child("uppercase").set(uppercase);
    },
);

پایتون

@db_fn.on_value_created(reference="/messages/{pushId}/original")
def makeuppercase(event: db_fn.Event[Any]) -> None:
    """Listens for new messages added to /messages/{pushId}/original and
    creates an uppercase version of the message to /messages/{pushId}/uppercase
    """

    # Grab the value that was written to the Realtime Database.
    original = event.data
    if not isinstance(original, str):
        print(f"Not a string: {event.reference}")
        return

    # Use the Admin SDK to set an "uppercase" sibling.
    print(f"Uppercasing {event.params['pushId']}: {original}")
    upper = original.upper()
    parent = db.reference(event.reference).parent
    if parent is None:
        print("Message can't be root node.")
        return
    parent.child("uppercase").set(upper)

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

برای رویدادهای write یا update ، ویژگی data یک شیء Change است که شامل دو تصویر لحظه‌ای است که وضعیت داده‌ها را قبل و بعد از رویداد آغازین نشان می‌دهد. شیء Change دارای یک ویژگی before است که به شما امکان می‌دهد آنچه را که قبل از رویداد در Realtime Database ذخیره شده است، بررسی کنید و یک ویژگی after که وضعیت داده‌ها را پس از وقوع رویداد نشان می‌دهد.

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

نود جی اس

  exports makeUppercase = onValueWritten("/messages/{pushId}/original", (event) => {
        // Only edit data when it is first created.
        if (event.data.before.exists()) {
          return null;
        }
        // Exit when the data is deleted.
        if (!event.data.after.exists()) {
          return null;
        }
        // Grab the current value of what was written to the Realtime Database.
        const original = event.data.after.val();
        console.log('Uppercasing', event.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 event.data.after.ref.parent.child('uppercase').set(uppercase);
      });

پایتون

@db_fn.on_value_written(reference="/messages/{pushId}/original")
def makeuppercase2(event: db_fn.Event[db_fn.Change]) -> None:
    """Listens for new messages added to /messages/{pushId}/original and
    creates an uppercase version of the message to /messages/{pushId}/uppercase
    """

    # Only edit data when it is first created.
    if event.data.before is not None:
        return

    # Exit when the data is deleted.
    if event.data.after is None:
        return

    # Grab the value that was written to the Realtime Database.
    original = event.data.after
    if not hasattr(original, "upper"):
        print(f"Not a string: {event.reference}")
        return

    # Use the Admin SDK to set an "uppercase" sibling.
    print(f"Uppercasing {event.params['pushId']}: {original}")
    upper = original.upper()
    parent = db.reference(event.reference).parent
    if parent is None:
        print("Message can't be root node.")
        return
    parent.child("uppercase").set(upper)