מפעילים של Cloud Firestore


עם פונקציות ענן, אתה יכול לטפל באירועים ב-Cloud Firestore ללא צורך בעדכון קוד הלקוח. אתה יכול לבצע שינויים ב-Cloud Firestore דרך ממשק תמונת המצב של המסמך או דרך ה- Admin SDK .

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

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

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

הפעלת פונקציית Cloud Firestore

ה-Cloud Functions for Firebase SDK מייצא אובייקט functions.firestore המאפשר לך ליצור מטפלים הקשורים לאירועי Cloud Firestore ספציפיים.

סוג אירוע הדק
onCreate מופעל כאשר נכתבים למסמך בפעם הראשונה.
onUpdate מופעל כאשר מסמך כבר קיים וערך כלשהו השתנה.
onDelete מופעל כאשר מסמך עם נתונים נמחק.
onWrite מופעל כאשר onCreate , onUpdate או onDelete מופעלים.

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

כתיבת פונקציות שהופעלו על ידי Cloud Firestore

הגדר מפעיל פונקציה

כדי להגדיר טריגר של Cloud Firestore, ציין נתיב מסמך וסוג אירוע:

Node.js

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

exports.myFunction = functions.firestore
  .document('my-collection/{docId}')
  .onWrite((change, context) => { /* ... */ });

נתיבי מסמכים יכולים להתייחס למסמך ספציפי או לתבנית כללית .

ציין מסמך בודד

אם ברצונך להפעיל אירוע עבור כל שינוי במסמך מסוים, תוכל להשתמש בפונקציה הבאה.

Node.js

// Listen for any change on document `marie` in collection `users`
exports.myFunctionName = functions.firestore
    .document('users/marie').onWrite((change, context) => {
      // ... Your code here
    });

ציין קבוצת מסמכים באמצעות תווים כלליים

אם ברצונך לצרף טריגר לקבוצת מסמכים, כגון כל מסמך באוסף מסוים, השתמש ב- {wildcard} במקום מזהה המסמך:

Node.js

// Listen for changes in all documents in the 'users' collection
exports.useWildcard = functions.firestore
    .document('users/{userId}')
    .onWrite((change, context) => {
      // If we set `/users/marie` to {name: "Marie"} then
      // context.params.userId == "marie"
      // ... and ...
      // change.after.data() == {name: "Marie"}
    });

בדוגמה זו, כאשר שדה כלשהו במסמך כלשהו users משתנה, הוא תואם לתווים כלליים בשם userId .

אם למסמך users יש תת-אוספים, ושדה באחד ממסמכי המשנה של אותם תת-אוספים משתנה, התו הכללי userId לא יופעל.

התאמות עם תווים כלליים נשלפים מנתיב המסמך ומאוחסנות ב- context.params . אתה יכול להגדיר כמה תווים כלליים שתרצה במקום מזהי אוסף או מסמכים מפורשים, לדוגמה:

Node.js

// Listen for changes in all documents in the 'users' collection and all subcollections
exports.useMultipleWildcards = functions.firestore
    .document('users/{userId}/{messageCollectionId}/{messageId}')
    .onWrite((change, context) => {
      // If we set `/users/marie/incoming_messages/134` to {body: "Hello"} then
      // context.params.userId == "marie";
      // context.params.messageCollectionId == "incoming_messages";
      // context.params.messageId == "134";
      // ... and ...
      // change.after.data() == {body: "Hello"}
    });

מפעילי אירועים

הפעל פונקציה כאשר מסמך חדש נוצר

אתה יכול להפעיל פונקציה להפעלה בכל פעם שמסמך חדש נוצר באוסף על ידי שימוש במטפל onCreate() עם תו כללי . פונקציה זו לדוגמה קוראת ל- createUser בכל פעם שמתווסף פרופיל משתמש חדש:

Node.js

exports.createUser = functions.firestore
    .document('users/{userId}')
    .onCreate((snap, context) => {
      // Get an object representing the document
      // e.g. {'name': 'Marie', 'age': 66}
      const newValue = snap.data();

      // access a particular field as you would any JS property
      const name = newValue.name;

      // perform desired operations ...
    });

הפעל פונקציה כאשר מסמך מתעדכן

אתה יכול גם להפעיל פונקציה להפעלה כאשר מסמך מתעדכן באמצעות הפונקציה onUpdate() עם תו כללי . פונקציה זו לדוגמה קוראת ל- updateUser אם משתמש משנה את הפרופיל שלו:

Node.js

exports.updateUser = functions.firestore
    .document('users/{userId}')
    .onUpdate((change, context) => {
      // Get an object representing the document
      // e.g. {'name': 'Marie', 'age': 66}
      const newValue = change.after.data();

      // ...or the previous value before this update
      const previousValue = change.before.data();

      // access a particular field as you would any JS property
      const name = newValue.name;

      // perform desired operations ...
    });

הפעל פונקציה כאשר מסמך נמחק

אתה יכול גם להפעיל פונקציה כאשר מסמך נמחק באמצעות הפונקציה onDelete() עם תו כללי . פונקציה זו לדוגמה קוראת ל- deleteUser כאשר משתמש מוחק את פרופיל המשתמש שלו:

Node.js

exports.deleteUser = functions.firestore
    .document('users/{userID}')
    .onDelete((snap, context) => {
      // Get an object representing the document prior to deletion
      // e.g. {'name': 'Marie', 'age': 66}
      const deletedValue = snap.data();

      // perform desired operations ...
    });

הפעל פונקציה עבור כל השינויים במסמך

אם לא אכפת לך מסוג האירוע המופעל, תוכל להאזין לכל השינויים במסמך Cloud Firestore באמצעות הפונקציה onWrite() עם תו כללי . פונקציה זו לדוגמה קוראת ל- modifyUser אם משתמש נוצר, מעודכן או נמחק:

Node.js

exports.modifyUser = functions.firestore
    .document('users/{userID}')
    .onWrite((change, context) => {
      // Get an object with the current document value.
      // If the document does not exist, it has been deleted.
      const document = change.after.exists ? change.after.data() : null;

      // Get an object with the previous document value (for update or delete)
      const oldDocument = change.before.data();

      // perform desired operations ...
    });

קריאה וכתיבה של נתונים

כאשר פונקציה מופעלת, היא מספקת תמונת מצב של הנתונים הקשורים לאירוע. אתה יכול להשתמש בתמונת מצב זו כדי לקרוא או לכתוב למסמך שהפעיל את האירוע, או להשתמש ב-SDK של Firebase Admin כדי לגשת לחלקים אחרים במסד הנתונים שלך.

נתוני אירועים

קריאת נתונים

כאשר פונקציה מופעלת, ייתכן שתרצה לקבל נתונים ממסמך שעודכן, או לקבל את הנתונים לפני העדכון. אתה יכול לקבל את הנתונים הקודמים באמצעות change.before.data() , המכיל את תמונת המצב של המסמך לפני העדכון. באופן דומה, change.after.data() מכיל את מצב תמונת המצב של המסמך לאחר העדכון.

Node.js

exports.updateUser2 = functions.firestore
    .document('users/{userId}')
    .onUpdate((change, context) => {
      // Get an object representing the current document
      const newValue = change.after.data();

      // ...or the previous value before this update
      const previousValue = change.before.data();
    });

אתה יכול לגשת למאפיינים כמו בכל אובייקט אחר. לחלופין, אתה יכול להשתמש בפונקציה get כדי לגשת לשדות ספציפיים:

Node.js

// Fetch data using standard accessors
const age = snap.data().age;
const name = snap.data()['name'];

// Fetch data using built in accessor
const experience = snap.get('experience');

כתיבת נתונים

כל הפעלת פונקציה משויכת למסמך ספציפי במסד הנתונים שלך ב-Cloud Firestore. אתה יכול לגשת למסמך זה בתור DocumentReference במאפיין ref של תמונת המצב שהוחזרה לפונקציה שלך.

DocumentReference זה מגיע מה- Cloud Firestore Node.js SDK וכולל שיטות כמו update() , set() ו- remove() כך שתוכלו לשנות בקלות את המסמך שהפעיל את הפונקציה.

Node.js

// Listen for updates to any `user` document.
exports.countNameChanges = functions.firestore
    .document('users/{userId}')
    .onUpdate((change, context) => {
      // Retrieve the current and previous value
      const data = change.after.data();
      const previousData = change.before.data();

      // We'll only update if the name has changed.
      // This is crucial to prevent infinite loops.
      if (data.name == previousData.name) {
        return null;
      }

      // Retrieve the current count of name changes
      let count = data.name_change_count;
      if (!count) {
        count = 0;
      }

      // Then return a promise of a set operation to update the count
      return change.after.ref.set({
        name_change_count: count + 1
      }, {merge: true});
    });

נתונים מחוץ לאירוע הטריגר

פונקציות ענן פועלות בסביבה מהימנה, מה שאומר שהן מורשות כחשבון שירות בפרויקט שלך. אתה יכול לבצע קריאה וכתיבה באמצעות Firebase Admin SDK :

Node.js

const admin = require('firebase-admin');
admin.initializeApp();

const db = admin.firestore();

exports.writeToFirestore = functions.firestore
  .document('some/doc')
  .onWrite((change, context) => {
    db.doc('some/otherdoc').set({ ... });
  });

מגבלות

שימו לב למגבלות הבאות עבור טריגרים של Cloud Firestore עבור פונקציות ענן:

  • ההזמנה אינה מובטחת. שינויים מהירים יכולים להפעיל הפעלות לפונקציה בסדר לא צפוי.
  • אירועים מועברים לפחות פעם אחת, אך אירוע בודד עלול לגרום למספר הפעלות לפונקציות. הימנע מהתלות במכניקה של פעם אחת בדיוק, וכתוב פונקציות אימפוטנטיות .
  • Cloud Firestore במצב Datastore דורש פונקציות ענן (דור שני). Cloud Functions (דור ראשון) אינו תומך במצב Datastore.
  • Cloud Functions (דור ראשון) פועלת רק עם מסד נתונים "(ברירת מחדל)" ואינה תומכת בבסיסי נתונים בעלי שם של Cloud Firestore. אנא השתמש ב-Cloud Functions (דור שני) כדי להגדיר אירועים עבור מסדי נתונים בעלי שם.
  • טריגר משויך למסד נתונים בודד. לא ניתן ליצור טריגר התואם מסדי נתונים מרובים.
  • מחיקת מסד נתונים אינה מוחקת באופן אוטומטי כל טריגרים עבור מסד נתונים זה. הטריגר מפסיק לספק אירועים אך ממשיך להתקיים עד שתמחק את הטריגר .
  • אם אירוע מותאם חורג מגודל הבקשה המקסימלי , ייתכן שהאירוע לא יימסר ל-Cloud Functions (דור ראשון).
    • אירועים שלא נמסרו בגלל גודל הבקשה נרשמים ביומני הפלטפורמה ונספרים עבור השימוש ביומן עבור הפרויקט.
    • אתה יכול למצוא את היומנים האלה בסייר היומנים עם ההודעה "אירוע אינו יכול להעביר לפונקציית הענן עקב גודל החורג מהמגבלה עבור הדור הראשון..." של חומרת error . אתה יכול למצוא את שם הפונקציה תחת השדה functionName . אם השדה receiveTimestamp עדיין בתוך שעה מהיום, תוכל להסיק את תוכן האירוע בפועל על ידי קריאת המסמך המדובר עם תמונת מצב לפני ואחרי חותמת הזמן.
    • כדי להימנע מקצב כזה, אתה יכול:
      • העבר ושדרוג ל-Cloud Functions (דור שני)
      • הקטנת המסמך
      • מחק את פונקציות הענן המדוברות
    • אתה יכול לכבות את הרישום עצמו באמצעות אי הכללות אך שים לב שהאירועים הפוגעים עדיין לא יועברו.