रीयलटाइम डेटाबेस ट्रिगर

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 इवेंट के जवाब देने के लिए, ये हैंडलर उपलब्ध हैं:

Node.js

  • onValueWritten() इस सूचना को तब ट्रिगर किया जाता है, जब Realtime Database में डेटा बनाया जाता है, अपडेट किया जाता है या मिटाया जाता है.
  • onValueCreated() यह सिर्फ़ तब ट्रिगर होता है, जब Realtime Database में डेटा बनाया जाता है.
  • onValueUpdated() यह सिर्फ़ तब ट्रिगर होता है, जब Realtime Database में डेटा अपडेट किया जाता है.
  • onValueDeleted() यह सिर्फ़ तब ट्रिगर होता है, जब Realtime Database में डेटा मिटाया जाता है.

Python

  • on_value_written() इस सूचना को तब ट्रिगर किया जाता है, जब Realtime Database में डेटा बनाया जाता है, अपडेट किया जाता है या मिटाया जाता है.
  • on_value_created() यह सिर्फ़ तब ट्रिगर होता है, जब Realtime Database में डेटा बनाया जाता है.
  • on_value_updated() यह सिर्फ़ तब ट्रिगर होता है, जब Realtime Database में डेटा अपडेट किया जाता है.
  • on_value_deleted() यह सिर्फ़ तब ट्रिगर होता है, जब Realtime Database में डेटा मिटाया जाता है.

ज़रूरी मॉड्यूल इंपोर्ट करना

आपको अपने फ़ंक्शन के सोर्स में, उन SDK मॉड्यूल को इंपोर्ट करना होगा जिनका आपको इस्तेमाल करना है. इस सैंपल के लिए, एचटीटीपी और Realtime Database मॉड्यूल के साथ-साथ, Realtime Database में लिखने के लिए Firebase Admin SDK मॉड्यूल को इंपोर्ट करना ज़रूरी है.

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();

Python

# 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) => {
    // …
  }
);

Python

# 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}.

कैप्चर किए गए वैरिएबल की वैल्यू, आपके फ़ंक्शन के database.DatabaseEvent.params ऑब्जेक्ट में उपलब्ध होती हैं.

इंस्टेंस वाइल्डकार्डिंग. वाइल्डकार्ड का इस्तेमाल करके, इंस्टेंस कॉम्पोनेंट भी तय किया जा सकता है. उदाहरण के लिए, इंस्टेंस वाइल्डकार्ड में प्रीफ़िक्स, सफ़िक्स या दोनों हो सकते हैं (जैसे, my-app-*-prod).

वाइल्डकार्ड और कैप्चर रेफ़रंस

Cloud Functions (दूसरी जनरेशन) और Realtime Database की मदद से, ref और instance की जानकारी देते समय किसी पैटर्न का इस्तेमाल किया जा सकता है. हर ट्रिगर इंटरफ़ेस में, फ़ंक्शन को स्कोप करने के लिए ये विकल्प होंगे:

ref तय करना instance तय करना व्यवहार
सिंगल (/foo/bar) जानकारी नहीं दी गई है फ़ंक्शन के क्षेत्र में मौजूद सभी इंस्टेंस के लिए, स्कोप हैंडलर.
सिंगल (/foo/bar) सिंगल (‘my-new-db') यह फ़ंक्शन के क्षेत्र में मौजूद खास इंस्टेंस के लिए, स्कोप हैंडलर होता है.
सिंगल (/foo/bar) पैटर्न (‘inst-prefix*') यह फ़ंक्शन क्षेत्र में पैटर्न से मेल खाने वाले सभी इंस्टेंस के लिए, स्कोप हैंडलर होता है.
पैटर्न (/foo/{bar}) जानकारी नहीं दी गई है फ़ंक्शन के क्षेत्र में मौजूद सभी इंस्टेंस के लिए, स्कोप हैंडलर.
पैटर्न (/foo/{bar}) सिंगल (‘my-new-db') यह फ़ंक्शन के क्षेत्र में मौजूद खास इंस्टेंस के लिए, स्कोप हैंडलर होता है.
पैटर्न (/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);
    },
);

Python

@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);
      });

Python

@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)