Catch up on everthing we announced at this year's Firebase Summit. Learn more

מפעילי מסדי נתונים

בעזרת פונקציות ענן, תוכל להתמודד עם אירועים במסד הנתונים בזמן אמת של Firebase ללא צורך בעדכון קוד לקוח. Cloud Functions מאפשר לך להפעיל פעולות מסד נתונים בזמן אמת עם הרשאות ניהול מלאות, ומבטיח שכל שינוי במאגר הנתונים בזמן אמת יעובד בנפרד. באפשרותך לבצע שינויים מסד Firebase זמן אמת באמצעות DataSnapshot או באמצעות SDK של ניהול .

במחזור חיים טיפוסי, פונקציית מסד נתונים בזמן אמת של Firebase עושה את הפעולות הבאות:

  1. ממתין לשינויים במיקום מסד נתונים בזמן אמת מסוים.
  2. מפעיל כאשר מתרחש אירוע ומבצע המשימות שלה (ראה מה אני יכול לעשות עם פונקציות ענן? דוגמאות של מקרי שימוש).
  3. מקבל אובייקט נתונים המכיל תמונת מצב של הנתונים המאוחסנים במסמך שצוין.

הפעלת פונקציית מסד נתונים בזמן אמת

צור פונקציות חדשות עבור אירועי מסד זמן אמת עם functions.database . כדי לקבוע מתי הפונקציה מפעילה, ציין אחד ממפעלי האירועים וציין את נתיב מסד הנתונים בזמן אמת שבו הוא יקשיב לאירועים.

הגדר את מטפל האירועים

פונקציות מאפשרות לך להתמודד עם אירועי מסד נתונים בזמן אמת בשתי רמות ספציפיות; אתה יכול להאזין במיוחד לאירועי יצירה, עדכון או מחיקה בלבד, או שאתה יכול להאזין לכל שינוי מכל סוג שהוא לנתיב. Cloud Functions תומך במפעלי אירועים אלה למסד נתונים בזמן אמת:

  • onWrite() , אשר מפעילה כאשר הנתונים נוצר, מעודכן, או נמחק מסד זמן אמת.
  • onCreate() , אשר מפעיל כאשר נתונים חדשים נוצר מסד זמן אמת.
  • onUpdate() , אשר מפעילה כאשר הנתונים מתעדכן מסד זמן אמת.
  • onDelete() , אשר מפעיל כאשר נתון נמחקים מסד זמן אמת.

ציין את המופע והנתיב

לשלוט מתי והיכן הפונקציה שלך צריכה לעורר, שיחת ref(path) כדי לציין נתיב, וכן לציין למשל מסד זמן אמת עם instance('INSTANCE_NAME') . אם אינך מציין מופע, הפונקציה מתפרסת למופע ברירת המחדל של מסד נתונים בזמן אמת עבור פרויקט Firebase לדוגמה:

  • מחדל למשל מסד זמן אמת: functions.database.ref('/foo/bar')
  • מופע בשם "שלי-app-db-2": functions.database.instance('my-app-db-2').ref('/foo/bar')

שיטות אלה מכוונות את הפונקציה שלך לטפל בכתיבות בנתיב מסוים בתוך מופע מסד הנתונים בזמן אמת. מפרטים נתיב להתאים כל פעולות כתיבה לגעת נתיב, כולל כותב שקורים בכל מקום מתחתיה. אם אתה מגדיר את הנתיב עבור הפונקציה שלך כמו /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 רכוש המאפשר לך לבדוק מה ניצל כדי Database זמן אמת לפני האירוע. before תשואות נכס DataSnapshot שבו כל שיטות (למשל, val() ו exists() ) מתייחס לערך הקודם. אתה יכול לקרוא את הערך החדש שוב על ידי שימוש המקורי DataSnapshot או קריאה after הרכוש. מאפיין זה על כל Change הוא עוד DataSnapshot המייצג את מצב הנתונים לאחר האירוע קרה.

לדוגמא, 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);
    });