אחזור נתונים

קריאת נתונים באמצעות GET

אנחנו יכולים לקרוא נתונים ממסד הנתונים של Firebase על ידי שליחת בקשת GET לנקודת הקצה של כתובת ה-URL שלו. נמשיך עם דוגמת הבלוג מהקטע הקודם ונקריא את כל הנתונים של הפוסט בבלוג:

curl 'https://docs-examples.firebaseio.com/fireblog/posts.json?print=pretty'

בקשה שהצליחה תסומן בקוד סטטוס HTTP‏ 200 OK, והתגובה תכיל את הנתונים שאנחנו מאחזרים.

הוספת פרמטרים של URI

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

auth

פרמטר הבקשה auth מאפשר גישה לנתונים שמוגנים על ידי Firebase Realtime Database Security Rules, וכל סוגי הבקשות תומכים בו. הארגומנט יכול להיות הסוד של אפליקציית Firebase או אסימון אימות, כפי שמתואר בקטע משתמשים בפרויקטים של Firebase. בדוגמה הבאה אנחנו שולחים בקשה מסוג GET עם הפרמטר auth, כאשר CREDENTIAL הוא הסוד של אפליקציית Firebase או אסימון אימות:

curl 'https://docs-examples.firebaseio.com/auth-example.json?auth=CREDENTIAL'

הדפס

ציון הערך print=pretty מחזיר את הנתונים בפורמט קריא לבני אדם.

curl 'https://docs-examples.firebaseio.com/fireblog/posts.json?print=pretty'

אם מציינים את print=silent, הפונקציה מחזירה 204 No Content אם הפעולה הושלמה בהצלחה.

curl 'https://docs-examples.firebaseio.com/fireblog/posts.json?print=silent'

קריאה חוזרת (callback)

כדי לבצע קריאות REST מדפדפן אינטרנט בתחומים שונים, אפשר להשתמש ב-JSONP כדי לעטוף את התגובה בפונקציית קריאה חוזרת של JavaScript. מוסיפים את callback= כדי לאפשר ל-API ל-REST לעטוף את הנתונים המוחזרים בפונקציית הקריאה החוזרת שציינתם. לדוגמה:

<script>
  function gotData(data) {
    console.log(data);
  }
</script>
<script src="https://docs-examples.firebaseio.com/fireblog/posts.json?callback=gotData">

שטחי

זוהי תכונה מתקדמת שנועדה לעזור לכם לעבוד עם מערכי נתונים גדולים בלי שתצטרכו להוריד את כולם. כדי להשתמש בו, מוסיפים את shallow=true כפרמטר. כך תוכלו להגביל את עומק הנתונים שיוחזרו. אם הנתונים במיקום הם פרימיטיבי JSON (מחרוזת, מספר או ערך בוליאני), הערך שלהם יוחזר. אם קובץ snapshot של הנתונים במיקום הוא אובייקט JSON, הערכים של כל מפתח יקוצצו ל-true. לדוגמה, באמצעות הנתונים הבאים:

{
  "message": {
    "user": {
      "name": "Chris"
    },
    "body": "Hello!"
  }
}

// A request to /message.json?shallow=true
// would return the following:
{
  "user": true,
  "body": true
}

// A request to /message/body.json?shallow=true
// would simply return:
"Hello!"

אפשר לנסות את זה באמצעות הבקשה הבאה ל-curl:

curl 'https://docs-examples.firebaseio.com/rest/retrieving-data.json?shallow=true&print=pretty'

זמן קצוב לתפוגה

אפשר להשתמש באפשרות הזו כדי להגביל את משך הזמן של הקריאה בצד השרת. אם בקשת קריאה לא מסתיימת בזמן המוקצב, היא מסתיימת עם שגיאת HTTP 400. האפשרות הזו שימושית במיוחד כשצפויה העברה של כמות קטנה של נתונים, ולא רוצים להמתין זמן רב מדי כדי לאחזר עץ משנה שעשוי להיות גדול מאוד. זמן הקריאה בפועל עשוי להשתנות בהתאם לגודל הנתונים ולאחסון במטמון.

מציינים את timeouts בפורמט הבא: 3ms,‏ 3s או 3min, עם מספר ויחידת מידה. אם לא מציינים ערך, יוחל הערך המקסימלי של timeout, שהוא 15min. אם הערך של timeout לא חיובי או שהוא חורג מהערך המקסימלי, הבקשה תידחה עם שגיאת HTTP 400. בדוגמה הבאה, הבקשה GET כוללת timeout של 10 שניות.

curl 'https://docs-examples.firebaseio.com/rest/retrieving-data.json?timeout=10s'

סינון נתונים

אנחנו יכולים ליצור שאילתות כדי לסנן נתונים על סמך גורמים שונים. בשלב הראשון, מציינים את האופן שבו רוצים לסנן את הנתונים באמצעות הפרמטר orderBy. לאחר מכן, משלבים את orderBy עם כל אחד מחמשת הפרמטרים האחרים: limitToFirst, limitToLast, startAt, endAt ו-equalTo.

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

{
  "lambeosaurus": {
    "height": 2.1,
    "length": 12.5,
    "weight": 5000
  },
  "stegosaurus": {
    "height": 4,
    "length": 9,
    "weight": 2500
  }
}

אנחנו יכולים לסנן נתונים באחת משלוש דרכים: לפי מפתח צאצא, לפי מפתח או לפי ערך. שאילתה מתחילה באחד מהפרמטרים האלה, ולאחר מכן צריך לשלב אותה עם אחד או יותר מהפרמטרים הבאים: startAt,‏ endAt,‏ limitToFirst,‏ limitToLast או equalTo.

סינון לפי מפתח צאצא ספציפי

אפשר לסנן צמתים לפי מפתח צאצא משותף על ידי העברת המפתח הזה לפרמטר orderBy. לדוגמה, כדי לאחזר את כל הדינוזאורים שגובהם גדול מ-3, אפשר לבצע את הפעולות הבאות:

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="height"&startAt=3&print=pretty'

כל צומת שאין לו את מפתח הצאצא שאנחנו מסננים לפיו ימוין עם הערך null. לפרטים על סדר הנתונים, ראו סדר הנתונים.

ב-Firebase יש גם תמיכה בשאילתות שממוינות לפי צאצאים שמוטמעים לעומק, ולא רק לפי צאצאים ברמה אחת למטה. האפשרות הזו שימושית אם יש לכם נתונים שמקובצים לעומק, כמו זה:

{
  "lambeosaurus": {
    "dimensions": {
      "height" : 2.1,
      "length" : 12.5,
      "weight": 5000
    }
  },
  "stegosaurus": {
    "dimensions": {
      "height" : 4,
      "length" : 9,
      "weight" : 2500
    }
  }
}

כדי לשלוח שאילתות לגבי הגובה, אנחנו משתמשים עכשיו בנתיב המלא לאובייקט במקום במפתח יחיד:

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="dimensions/height"&startAt=3&print=pretty'

אפשר לסנן שאילתות לפי מפתח אחד בלבד בכל פעם. שימוש בפרמטר orderBy כמה פעמים באותה בקשה יגרום לשגיאה.

סינון לפי מפתח

אפשר גם לסנן צמתים לפי המפתחות שלהם באמצעות הפרמטר orderBy="$key". בדוגמה הבאה מתבצעת אחזור של כל הדינוזאורים שהשם שלהם מתחיל באות a ועד m:

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="$key"&startAt="a"&endAt="m"&print=pretty'

סינון לפי ערך

אפשר לסנן צמתים לפי הערך של מפתחות הצאצאים שלהם באמצעות הפרמטר orderBy="$value". נניח שהדינוזאורים מקיימים תחרות ספורט דינוזאורים, ואנחנו עוקבים אחרי התוצאות שלהם בפורמט הבא:

{
  "scores": {
    "bruhathkayosaurus": 55,
    "lambeosaurus": 21,
    "linhenykus": 80,
    "pterodactyl": 93,
    "stegosaurus": 5,
    "triceratops": 22
  }
}

כדי לאחזר את כל הדינוזאורים עם ציון גבוה מ-50, אפשר לשלוח את הבקשה הבאה:

curl 'https://dinosaur-facts.firebaseio.com/scores.json?orderBy="$value"&startAt=50&print=pretty'

במאמר איך הנתונים ממוינים מוסבר איך מתבצעת המיון של ערכים מסוג null, בוליאני, מחרוזת ואובייקט כשמשתמשים ב-orderBy="$value".

סינון מורכב

אנחנו יכולים לשלב כמה פרמטרים כדי ליצור שאילתות מורכבות יותר.

הגבלת שאילתות

הפרמטרים limitToFirst ו-limitToLast משמשים להגדרת מספר הילדים המקסימלי שעבורם יקבלו נתונים. אם נגדיר מגבלה של 100, נקבל רק עד 100 ילדים תואמים. אם יש לנו פחות מ-100 הודעות שמאוחסנות במסד הנתונים שלנו, נקבל כל ילד או ילדה. עם זאת, אם יש יותר מ-100 הודעות, נקבל נתונים רק לגבי 100 מההודעות האלה. אלה יהיו 100 ההודעות הראשונות בסדר אם משתמשים ב-limitToFirst, או 100 ההודעות האחרונות בסדר אם משתמשים ב-limitToLast.

בעזרת מסד הנתונים של עובדות על דינוזאורים ו-orderBy, אפשר למצוא את שני הדינוזאורים הכי כבדים:

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="weight"&limitToLast=2&print=pretty'

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

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="height"&limitToFirst=2&print=pretty'

אפשר גם לבצע שאילתות עם הגבלות באמצעות orderBy="$value". אם רוצים ליצור לוח מנהיגות עם שלושת המתחרים המובילים עם הציון הגבוה ביותר בספורט הדינוזאורים, אפשר לבצע את הפעולות הבאות:

curl 'https://dinosaur-facts.firebaseio.com/scores.json?orderBy="$value"&limitToLast=3&print=pretty'

שאילתות טווח

השימוש ב-startAt, ב-endAt וב-equalTo מאפשר לנו לבחור נקודות התחלה וסיום שרירותיות לשאילתות שלנו. לדוגמה, אם נרצה למצוא את כל הדינוזאורים שגובהם לפחות שלושה מטרים, נוכל לשלב את orderBy ו-startAt:

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="height"&startAt=3&print=pretty'

אפשר להשתמש ב-endAt כדי למצוא את כל הדינוזאורים ששמותיהם מופיעים לפני Pterodactyl מבחינה לקסיקוגרפית:

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="$key"&endAt="pterodactyl"&print=pretty'

אפשר לשלב את startAt ו-endAt כדי להגביל את שני הקצוות של השאילתה. בדוגמה הבאה מוצגים כל הדינוזאורים שהשם שלהם מתחיל באות 'b':

curl 'https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy="$key"&startAt="b"&endAt="b\uf8ff"&print=pretty'

שאילתות טווח הן גם שימושיות כשצריך לפצל את הנתונים לדפים.

סיכום של כל המידע

אנחנו יכולים לשלב את כל השיטות האלה כדי ליצור שאילתות מורכבות. לדוגמה, אולי תרצו למצוא את השם של כל הדינוזאורים שגובהם נמוך מגובה הדינוזאור האהוב עלינו, הסטגוזאורוס, או שווה לו:

MY_FAV_DINO_HEIGHT=`curl "https://dinosaur-facts.firebaseio.com/dinosaurs/stegosaurus/height.json"`
curl "https://dinosaur-facts.firebaseio.com/dinosaurs.json?orderBy=\"height\"&endAt=${MY_FAV_DINO_HEIGHT}&print=pretty"

סדר הנתונים

בקטע הזה מוסבר איך הנתונים ממוינים כשמשתמשים בכל אחד משלושת הפרמטרים לסינון.

orderBy

כשמשתמשים ב-orderBy עם שם של מפתח צאצא, הנתונים שמכילים את מפתח הצאצא שצוין יסודרו באופן הבא:

  1. צאצאים עם ערך null למפתח הצאצא שצוין מופיעים קודם.
  2. לאחר מכן מופיעים צאצאים עם הערך false למפתח הצאצא שצוין. אם יש כמה צאצאים עם הערך false, הם ממוינים לפי אלפבית לפי מפתח.
  3. לאחר מכן מופיעים צאצאים עם הערך true למפתח הצאצא שצוין. אם יש כמה צאצאים עם הערך true, הם ממוינים לפי מפתח אלפביתי.
  4. לאחר מכן מופיעים צאצאים עם ערך מספרי, שממוינים בסדר עולה. אם ליותר מילד אחד יש את אותו ערך מספרי בצומת הצאצא שצוין, הם ממוינים לפי מפתח.
  5. מחרוזות מופיעות אחרי מספרים וממוינות לפי סדר אלפביתי עולה. אם לכמה צאצאים יש אותו ערך בצומת הצאצא שצוין, הם ממוינים לפי מפתח אלפביתי.
  6. האובייקטים מופיעים בסוף וממוינים לפי מפתח מילוני בסדר עולה.
התוצאות המסוננות מוחזרות ללא סדר. אם הסדר של הנתונים חשוב לכם, כדאי למיין את התוצאות באפליקציה אחרי שהן יחזרו מ-Firebase.

orderBy="$key"

כשמשתמשים בפרמטר orderBy="$key" כדי למיין את הנתונים, הנתונים יחזרו בסדר עולה לפי מפתח, באופן הבא. חשוב לזכור שמפתחות יכולים להיות רק מחרוזות.

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

orderBy="$value"

כשמשתמשים בפרמטר orderBy="$value" כדי למיין את הנתונים, הצאצאים ימוינו לפי הערך שלהם. קריטריונים למיון זהים לנתונים שממוינים לפי מפתח צאצא, מלבד שהמערכת משתמשת בערך הצומת במקום בערך של מפתח צאצא מסוים.

orderBy="$priority"

כשמשתמשים בפרמטר orderBy="$priority" כדי למיין את הנתונים, הסדר של הצאצאים נקבע לפי העדיפות והמפתח שלהם באופן הבא. חשוב לזכור שערכים של תעדוף יכולים להיות רק מספרים או מחרוזות.

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

למידע נוסף על רמות תעדוף, ראו הפניית API.

סטרימינג מה-API ל-REST

נקודות הקצה מסוג REST ב-Firebase תומכות בפרוטוקול EventSource / Server-Sent Events, כך שקל לשדר שינויים למיקום יחיד במסד הנתונים של Firebase.

כדי להתחיל בסטרימינג, נצטרך לבצע את הפעולות הבאות:

  1. מגדירים את הכותרת Accept של הלקוח ל-text/event-stream
  2. להקפיד על הפניות אוטומטיות מסוג HTTP, במיוחד על קוד מצב HTTP 307
  3. צריך לכלול את פרמטר השאילתה auth אם המיקום של מסד הנתונים ב-Firebase מחייב הרשאת קריאה

בתמורה, השרת ישלח אירועים עם שמות כשהמצב של הנתונים בכתובת ה-URL המבוקשת ישתנה. המבנה של ההודעות האלה תואם לפרוטוקול EventSource:

event: event name
data: JSON encoded data payload

השרת עשוי לשלוח את האירועים הבאים:

put הנתונים המקודדים ב-JSON יהיו אובייקט עם שני מפתחות: path ו-data
הנתיב מפנה למיקום ביחס לכתובת ה-URL של הבקשה
הלקוח צריך להחליף את כל הנתונים במיקום הזה במטמון שלו בנתונים שצוינו בהודעה
patch הנתונים בקידוד JSON יהיו אובייקט עם שני מפתחות: נתיב ונתונים
הנתיב מפנה למיקום ביחס לכתובת ה-URL של הבקשה
לכל מפתח בנתונים, הלקוח צריך להחליף את המפתח התואם במטמון שלו בנתונים של המפתח הזה בהודעה
הודעת keep-alive הנתונים של האירוע הזה הם null, לא נדרשת פעולה
cancel הנתונים של האירוע הזה הם null
האירוע הזה יישלח אם Firebase Realtime Database Security Rules גורם לכך שלא תהיה יותר הרשאה לקריאה במיקום המבוקש
auth_revoked הנתונים של האירוע הזה הם מחרוזת שמציינת שפג התוקף של פרטי הכניסה
האירוע הזה יישלח כשפרמטר האימות שסופק כבר לא תקף

בהמשך מוצגת דוגמה לקבוצת אירועים שהשרת עשוי לשלוח:

// Set your entire cache to {"a": 1, "b": 2}
event: put
data: {"path": "/", "data": {"a": 1, "b": 2}}


// Put the new data in your cache under the key 'c', so that the complete cache now looks like:
// {"a": 1, "b": 2, "c": {"foo": true, "bar": false}}
event: put
data: {"path": "/c", "data": {"foo": true, "bar": false}}


// For each key in the data, update (or add) the corresponding key in your cache at path /c,
// for a final cache of: {"a": 1, "b": 2, "c": {"foo": 3, "bar": false, "baz": 4}}
event: patch
data: {"path": "/c", "data": {"foo": 3, "baz": 4}}

אם אתם משתמשים ב-Go, כדאי לבדוק את Firego, חבילה של צד שלישי שמקיפה את ממשקי ה-API ל-REST ולסטרימינג של Firebase.