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


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

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

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

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

تنظیم مکان عملکرد

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

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

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

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

Node.js

  • 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 وارد کنید.

Node.js

// The Cloud Functions for Firebase SDK to setup triggers and logging.
const {onRequest} = require("firebase-functions/v2/https");
const {onValueCreated} = require("firebase-functions/v2/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 را برای استقرار در زیرمجموعه‌ای انتخابی از نمونه‌ها در همان منطقه مشخص کنید.

به عنوان مثال:

Node.js

// 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

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

وحشی و گرفتن

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

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

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

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

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

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

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

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

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

علامت عام و مرجع ضبط

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

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

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

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

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

Node.js

// 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 استفاده کرد تا مطمئن شویم که این تابع زمانی که برای اولین بار متن ایجاد می‌شود، فقط با حروف بزرگ نوشته می‌شود:

Node.js

  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)