אחזור נתונים

קריאת נתונים באמצעות 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 מאפשר גישה לנתונים שמוגנים על ידי 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 מההודעות האלה. אם אנחנו משתמשים ב-limitToFirst וב-100 ההודעות האחרונות, אם אנחנו משתמשים ב-limitToLast, אלה יהיו 100 ההודעות הראשונות שמסודרות.

בעזרת מסד הנתונים של עובדות על דינוזאורים ו-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". אם אנחנו רוצים ליצור Leaderboard עם שלושת המתחרים בעלי הדירוג הגבוה ביותר במשחקי דינו, נוכל לבצע את הפעולות הבאות:

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 כדי למצוא את כל הדינוזאורים שהשמות שלהם מופיעים לפני פטרודקטילוס בצורה מילונית:

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="$Priorityity"

כשמשתמשים בפרמטר 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 יהיו אובייקט עם שני מפתחות: path ו-data
הנתיב מפנה למיקום ביחס לכתובת ה-URL של הבקשה
לכל מפתח בנתונים, הלקוח צריך להחליף את המפתח התואם במטמון שלו בנתונים של המפתח הזה בהודעה
הודעת keep-alive הנתונים של האירוע הזה הם null, לא נדרשת פעולה
cancel הנתונים של האירוע הזה הם null
האירוע הזה נשלח אם Firebase Realtime Database Security Rules גורם לכך שלא תהיה יותר הרשאה לקריאה במיקום המבוקש
auth_revok הנתונים של האירוע הזה הם מחרוזת שמציינת שפג התוקף של פרטי הכניסה
האירוע הזה יישלח כשפרמטר האימות שסופק כבר לא תקף

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

// 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, wrapper של צד שלישי ל-REST ול-Stream API של Firebase.