במאמר הזה נסביר איך מאחזרים נתונים ואיך ממיינים ומסננים נתונים ב-Firebase.
לפני שמתחילים
צריך לוודא שהגדרתם את האפליקציה ויש לכם גישה למסד הנתונים, כמו שמוסבר במדריך Get Started
.
אחזור נתונים
הנתונים מ-Firebase מאוחזרים באמצעות קריאה חד-פעמית אל GetValue()
או באמצעות צירוף אל ValueListener
בהפניה אל FirebaseDatabase
. הפונקציה valueListener נקראת פעם אחת עבור המצב הראשוני של הנתונים, ועוד פעם בכל פעם שהנתונים משתנים.
קבלת DatabaseReference
כדי לכתוב נתונים למסד הנתונים, צריך מופע של DatabaseReference
:
// Get the root reference location of the database. firebase::database::DatabaseReference dbref = database->GetReference();
קריאת נתונים פעם אחת
אפשר להשתמש בשיטה GetValue()
כדי לקרוא פעם אחת תמונת מצב סטטית של התוכן בנתיב נתון. תוצאת המשימה תכיל תמונת מצב עם כל הנתונים במיקום הזה, כולל נתוני ילדים. אם אין נתונים, ה-snapshot שמוחזר הוא null
.
firebase::Future<firebase::database::DataSnapshot> result = dbRef.GetReference("Leaders").GetValue();
בנקודה שבה הבקשה בוצעה, אבל צריך לחכות עד שה-Future יסתיים כדי שאפשר יהיה לקרוא את הערך. משחקים בדרך כלל פועלים בלולאה, והם מבוססים פחות על קריאות חוזרות בהשוואה לאפליקציות אחרות, ולכן בדרך כלל מתבצעת בדיקה חוזרת כדי לראות אם הפעולה הושלמה.
// In the game loop that polls for the result... if (result.status() != firebase::kFutureStatusPending) { if (result.status() != firebase::kFutureStatusComplete) { LogMessage("ERROR: GetValue() returned an invalid result."); // Handle the error... } else if (result.error() != firebase::database::kErrorNone) { LogMessage("ERROR: GetValue() returned error %d: %s", result.error(), result.error_message()); // Handle the error... } else { firebase::database::DataSnapshot snapshot = result.result(); // Do something with the snapshot... } }
הדוגמה הזו מציגה בדיקת שגיאות בסיסית. אפשר לעיין בהפניה אל firebase::Future כדי לקבל מידע נוסף על בדיקת שגיאות ועל דרכים לקבוע מתי התוצאה מוכנה.
האזנה לאירועים
אפשר להוסיף מאזינים כדי להירשם לשינויים בנתונים:
ValueListener
מחלקה בסיסית
התקשרות חזרה | שימוש אופייני |
---|---|
OnValueChanged |
קריאה והאזנה לשינויים בכל התוכן של נתיב. |
OnChildListener
מחלקה בסיסית
OnChildAdded
| אחזור רשימות של פריטים או האזנה להוספות לרשימה של פריטים.
מומלץ להשתמש באפשרות הזו עם OnChildChanged ועם OnChildRemoved כדי לעקוב אחרי שינויים ברשימות. |
OnChildChanged |
חיפוש שינויים בפריטים ברשימה. אפשר להשתמש ב-OnChildAdded וב-OnChildRemoved כדי לעקוב אחרי שינויים ברשימות. |
OnChildRemoved |
האזנה להסרה של פריטים מרשימה. אפשר להשתמש ב-OnChildAdded וב-OnChildChanged כדי לעקוב אחרי שינויים ברשימות. |
OnChildMoved |
האזנה לשינויים בסדר הפריטים ברשימה ממוספרת.
OnChildMoved תמיד יתבצעו קודם קריאות חוזרות (callback) של
OnChildChanged כי הסדר של הפריטים משתנה (בהתאם לשיטת המיון הנוכחית). |
מחלקת ValueListener
אפשר להשתמש בOnValueChanged
פונקציות callback כדי להירשם לעדכונים בתוכן בנתיב מסוים. הקריאה החוזרת הזו מופעלת פעם אחת כשהמאזין מצורף, ופעם נוספת בכל פעם שהנתונים, כולל נתוני ילדים, משתנים. הקריאה החוזרת מקבלת תמונת מצב שמכילה את כל הנתונים במיקום הזה, כולל נתוני צאצא. אם אין נתונים, ה-snapshot שמוחזר הוא null
.
בדוגמה הבאה מוצג משחק ששולף את התוצאות של טבלת המובילים מהמסד הנתונים:
class LeadersValueListener : public firebase::database::ValueListener { public: void OnValueChanged( const firebase::database::DataSnapshot& snapshot) override { // Do something with the data in snapshot... } void OnCancelled(const firebase::database::Error& error_code, const char* error_message) override { LogMessage("ERROR: LeadersValueListener canceled: %d: %s", error_code, error_message); } }; // Elsewhere in the code... LeadersValueListener* listener = new LeadersValueListener(); firebase::Future<firebase::database::DataSnapshot> result = dbRef.GetReference("Leaders").AddValueListener(listener);
התוצאה של Future<DataSnapshot>
מכילה את הנתונים במיקום שצוין במסד הנתונים בזמן האירוע. התקשרות אל value()
בתמונת מצב
מחזירה Variant
שמייצג את הנתונים.
בדוגמה הזו, השיטה OnCancelled
מוחלפת גם כדי לבדוק אם הקריאה בוטלה. לדוגמה, אפשר לבטל קריאה אם ללקוח אין הרשאה לקרוא ממיקום במסד נתונים של Firebase. הערך database::Error
יציין את הסיבה לכשל.
המחלקות ChildListener
אירועים שקשורים לילדים מופעלים בתגובה לפעולות ספציפיות שמתרחשות לילדים של צומת מפעולה כמו הוספה של צומת צאצא חדש באמצעות השיטה PushChild()
או עדכון של צומת צאצא באמצעות השיטה UpdateChildren()
. כל אחת מהאפשרויות האלה יכולה להיות שימושית להאזנה לשינויים בצומת ספציפי במסד נתונים. לדוגמה, משחק יכול להשתמש בשיטות האלה ביחד כדי לעקוב אחרי הפעילות בתגובות של סשן משחק, כמו שמוצג בהמשך:
class SessionCommentsChildListener : public firebase::database::ChildListener { public: void OnChildAdded(const firebase::database::DataSnapshot& snapshot, const char* previous_sibling) override { // Do something with the data in snapshot ... } void OnChildChanged(const firebase::database::DataSnapshot& snapshot, const char* previous_sibling) override { // Do something with the data in snapshot ... } void OnChildRemoved( const firebase::database::DataSnapshot& snapshot) override { // Do something with the data in snapshot ... } void OnChildMoved(const firebase::database::DataSnapshot& snapshot, const char* previous_sibling) override { // Do something with the data in snapshot ... } void OnCancelled(const firebase::database::Error& error_code, const char* error_message) override { LogMessage("ERROR: SessionCommentsChildListener canceled: %d: %s", error_code, error_message); } }; // elsewhere .... SessionCommentsChildListener* listener = new SessionCommentsChildListener(); firebase::Future<firebase::database::DataSnapshot> result = dbRef.GetReference("GameSessionComments").AddChildListener(listener);
בדרך כלל משתמשים בפונקציית הקריאה החוזרת OnChildAdded
כדי לאחזר רשימה של פריטים במסד נתונים של Firebase. הפונקציה OnChildAdded
callback מופעלת פעם אחת לכל צאצא קיים, ואז שוב בכל פעם שמוסיפים צאצא חדש לנתיב שצוין. המאזין מקבל תמונת מצב שמכילה את הנתונים של הצאצא החדש.
הפונקציה OnChildChanged
נקראת בכל פעם שצומת משני משתנה.
השינויים האלה כוללים שינויים בצאצאים של צומת הילד. בדרך כלל משתמשים בו בשילוב עם הקריאות OnChildAdded
ו-OnChildRemoved
כדי להגיב לשינויים ברשימת פריטים. תמונת המצב שמועברת ל-listener מכילה את הנתונים המעודכנים של הרכיב המשני.
הקריאה החוזרת OnChildRemoved
מופעלת כשמסירים צאצא מיידי.
בדרך כלל משתמשים בה בשילוב עם פונקציות הקריאה החוזרת OnChildAdded
ו-OnChildChanged
. התמונה שמועברת לקריאה החוזרת מכילה את הנתונים של צאצא שהוסר.
הקריאה החוזרת OnChildMoved
מופעלת בכל פעם שהקריאה OnChildChanged
מופעלת על ידי עדכון שגורם לסידור מחדש של הילד. הוא משמש עם נתונים שמסודרים לפי OrderByChild
או OrderByValue
.
מיון וסינון של נתונים
אפשר להשתמש במחלקה Realtime Database Query
כדי לאחזר נתונים ממוינים לפי מפתח, לפי ערך או לפי ערך של צאצא. אפשר גם לסנן את התוצאה הממוינת לפי מספר מסוים של תוצאות או לפי טווח של מפתחות או ערכים.
מיון נתונים
כדי לאחזר נתונים ממוינים, צריך קודם לציין אחת משיטות המיון כדי לקבוע את סדר התוצאות:
שיטה | שימוש |
---|---|
OrderByChild() |
מיון התוצאות לפי הערך של מפתח צאצא ספציפי. |
OrderByKey()
| מיון התוצאות לפי מפתחות צאצא. |
OrderByValue() |
מיון התוצאות לפי ערכי הצאצא. |
אפשר להשתמש רק בשיטה אחת של מיון בכל פעם. הפעלת שיטה של מיון לפי סדר (order-by) מספר פעמים באותה שאילתה גורמת לשגיאה.
בדוגמה הבאה אפשר לראות איך נרשמים לטבלת מובילים של ניקוד, שמסודרת לפי ניקוד.
firebase::database::Query query = dbRef.GetReference("Leaders").OrderByChild("score"); // To get the resulting DataSnapshot either use query.GetValue() and poll the // future, or use query.AddValueListener() and register to handle the // OnValueChanged callback.
ההגדרה הזו מגדירה firebase::Query
שכאשר משלבים אותה עם ValueListener, היא מסנכרנת את הלקוח עם טבלת המובילים במסד הנתונים, לפי סדר הניקוד של כל רשומה.
במאמר איך מבנים את מסד הנתונים יש מידע נוסף על מבנה יעיל של הנתונים.
הקריאה ל-method OrderByChild()
מציינת את מפתח הילד כדי להזמין את התוצאות. במקרה הזה, התוצאות ממוינות לפי הערך של "score"
value בכל צאצא. מידע נוסף על הסדר של סוגי נתונים אחרים זמין במאמר איך מסודרים נתוני שאילתות.
סינון נתונים
כדי לסנן נתונים, אפשר לשלב כל אחת מהשיטות של הגבלה או טווח עם שיטת מיון כשיוצרים שאילתה.
שיטה | שימוש |
---|---|
LimitToFirst() |
מגדיר את המספר המקסימלי של פריטים שיוחזרו מתחילת רשימת התוצאות הממוינת. |
LimitToLast() |
מגדיר את המספר המקסימלי של פריטים שיוחזרו מסוף הרשימה הממוינת של התוצאות. |
StartAt() |
הפונקציה מחזירה פריטים שגדולים מהמפתח או מהערך שצוינו או שווים להם, בהתאם לשיטת המיון שנבחרה. |
EndAt() |
הפונקציה מחזירה פריטים שקטנים מהמפתח או מהערך שצוינו או שווים להם, בהתאם לשיטת המיון שנבחרה. |
EqualTo() |
הפונקציה מחזירה פריטים ששווים למפתח או לערך שצוינו, בהתאם לשיטת המיון שנבחרה. |
בניגוד לשיטות order-by, אפשר לשלב כמה פונקציות limit או range.
לדוגמה, אפשר לשלב בין השיטות StartAt()
ו-EndAt()
כדי להגביל את התוצאות לטווח ערכים מסוים.
גם אם יש רק התאמה אחת לשאילתה, התמונה היא עדיין רשימה, רק שהיא מכילה פריט אחד.
הגבלת מספר התוצאות
אפשר להשתמש בשיטות LimitToFirst()
ו-LimitToLast()
כדי להגדיר מספר מקסימלי של ילדים שיסונכרנו עבור קריאה חוזרת (callback) נתונה. לדוגמה, אם משתמשים ב-LimitToFirst()
כדי להגדיר מגבלה של 100, מקבלים בהתחלה רק עד 100 קריאות חוזרות של OnChildAdded
. אם יש לכם פחות מ-100 פריטים שמאוחסנים במסד הנתונים של Firebase, מתבצעת קריאה חוזרת (callback) של OnChildAdded
לכל פריט.
כשהפריטים משתנים, אתם מקבלים קריאות חוזרות (callback) מסוג OnChildAdded
לפריטים שנכנסים לשאילתה וקריאות חוזרות מסוג OnChildRemoved
לפריטים שיוצאים ממנה, כך שהמספר הכולל נשאר 100.
לדוגמה, הקוד הבא מחזיר את הציון הכי גבוה מטבלת מובילים:
firebase::database::Query query = dbRef.GetReference("Leaders").OrderByChild("score").LimitToLast(1); // To get the resulting DataSnapshot either use query.GetValue() and poll the // future, or use query.AddValueListener() and register to handle the // OnValueChanged callback.
סינון לפי מפתח או ערך
אפשר להשתמש בסימנים StartAt()
, EndAt()
ו-EqualTo()
כדי לבחור נקודות התחלה, סיום ושקילות שרירותיות לשאילתות. המאפיין הזה יכול להיות שימושי כשרוצים להציג נתונים בעמודים או למצוא פריטים עם פריטי צאצא שיש להם ערך ספציפי.
איך נתוני השאילתות מסודרים
בקטע הזה מוסבר איך הנתונים ממוינים לפי כל אחת מהשיטות של order-by במחלקה Query
.
OrderByChild
כשמשתמשים ב-OrderByChild()
, נתונים שמכילים את מפתח הצאצא שצוין מסודרים באופן הבא:
- ילדים עם ערך
null
למפתח הילד שצוין מופיעים ראשונים. - אחריהם מופיעים רכיבי צאצא עם הערך
false
עבור מפתח הצאצא שצוין. אם לכמה צאצאים יש ערך שלfalse
, הם ממוינים לקסיקוגרפית לפי מפתח. - אחריהם מופיעים רכיבי צאצא עם הערך
true
עבור מפתח הצאצא שצוין. אם לכמה צאצאים יש ערך שלtrue
, הם ממוינים לפי מפתח בסדר לקסיקוגרפי. - אחריהם מופיעים ילדים עם ערך מספרי, ממוינים בסדר עולה. אם לכמה צאצאים יש את אותו ערך מספרי בצומת הצאצא שצוין, הם ממוינים לפי מפתח.
- מחרוזות מופיעות אחרי מספרים וממוינות בסדר עולה לפי סדר מילוני. אם לכמה צאצאים יש את אותו ערך בצומת הצאצא שצוין, הם מסודרים לפי מפתח בסדר לקסיקוגרפי.
- האובייקטים מופיעים בסוף וממוינים בסדר עולה לפי מפתח, בסדר לקסיקוגרפי.
OrderByKey
כשמשתמשים ב-OrderByKey()
כדי למיין את הנתונים, הנתונים מוחזרים בסדר עולה לפי מפתח.
- הילדים עם מפתח שאפשר לנתח כמספר שלם בן 32 ביט מופיעים ראשונים, בסדר עולה.
- אחריהם מופיעים ילדים עם ערך מחרוזת כמפתח, ממוינים בסדר עולה לפי סדר מילוני.
OrderByValue
כשמשתמשים ב-OrderByValue()
, הילדים מסודרים לפי הערך שלהם. קריטריוני המיון זהים לאלה שמופיעים ב-OrderByChild()
, אלא שהערך של הצומת משמש במקום הערך של מפתח צאצא שצוין.