במאמר הזה נסביר את העקרונות הבסיסיים של אחזור נתונים ואיך לסדר ולסנן נתונים ב-Firebase.
לפני שמתחילים
לפני שתוכלו להשתמש ב-Realtime Database, אתם צריכים:
רושמים את הפרויקט ב-Unity ומגדירים אותו לשימוש ב-Firebase.
אם פרויקט Unity שלכם כבר משתמש ב-Firebase, הוא כבר רשום ומוגדר ל-Firebase.
אם אין לכם פרויקט ב-Unity, אתם יכולים להוריד אפליקציה לדוגמה.
מוסיפים את Firebase Unity SDK (באופן ספציפי,
FirebaseDatabase.unitypackage) לפרויקט ב-Unity.
שימו לב: הוספת Firebase לפרויקט ב-Unity כוללת משימות גם במסוף Firebase וגם בפרויקט הפתוח ב-Unity (לדוגמה, אתם מורידים קובצי תצורה של Firebase מהמסוף ואז מעבירים אותם לפרויקט ב-Unity).
אחזור נתונים
כדי לאחזר נתונים מ-Firebase, צריך לבצע קריאה חד-פעמית ל-GetValueAsync() או לצרף אירוע להפניה ל-FirebaseDatabase. הפונקציה event listener נקראת פעם אחת למצב הראשוני של הנתונים, ופעם נוספת בכל פעם שהנתונים משתנים.
קבלת DatabaseReference
כדי לקרוא נתונים ממסד הנתונים, צריך מופע של DatabaseReference:
using Firebase; using Firebase.Database; using Firebase.Extensions.TaskExtension; // for ContinueWithOnMainThread public class MyScript: MonoBehaviour { void Start() { // Get the root reference location of the database. DatabaseReference reference = FirebaseDatabase.DefaultInstance.RootReference; } }
קריאת נתונים פעם אחת
אפשר להשתמש ב-method GetValueAsync כדי לקרוא פעם אחת תמונת מצב סטטית של התוכן בנתיב נתון. תוצאת המשימה תכלול תמונת מצב עם כל הנתונים במיקום הזה, כולל נתוני הצאצאים. אם אין נתונים, תמונת המצב שמוחזרת היא null.
FirebaseDatabase.DefaultInstance .GetReference("Leaders") .GetValueAsync().ContinueWithOnMainThread(task => { if (task.IsFaulted) { // Handle the error... } else if (task.IsCompleted) { DataSnapshot snapshot = task.Result; // Do something with snapshot... } });
האזנה לאירועים
אתם יכולים להוסיף רכיבי event listener כדי להירשם לשינויים בנתונים:
| אירוע | שימוש אופייני |
|---|---|
ValueChanged |
קריאה וחיפוש של שינויים בכל התוכן של נתיב. |
ChildAdded
| אחזור רשימות של פריטים או האזנה לתוספות לרשימת פריטים.
מומלץ להשתמש עם ChildChanged ו-ChildRemoved כדי לעקוב אחרי שינויים ברשימות. |
ChildChanged |
האזנה לשינויים בפריטים ברשימה. אפשר להשתמש ב-ChildAdded וב-ChildRemoved כדי לעקוב אחרי שינויים ברשימות. |
ChildRemoved |
האזנה לפריטים שמוסרים מרשימה. אפשר להשתמש ב-ChildAdded וב-ChildChanged כדי לעקוב אחרי שינויים ברשימות. |
ChildMoved |
האזנה לשינויים בסדר הפריטים ברשימה ממוינת.
אירועי ChildMoved תמיד מגיעים אחרי האירוע ChildChanged שגרם לשינוי בסדר הפריטים (בהתאם לשיטת הסידור הנוכחית). |
אירוע ValueChanged
אתם יכולים להשתמש באירוע ValueChanged כדי להירשם לשינויים בתוכן בנתיב נתון. האירוע הזה מופעל פעם אחת כשהמאזין מצורף, ושוב בכל פעם שהנתונים משתנים, כולל הצאצאים. הקריאה החוזרת (callback) של האירוע מעבירה תמונת מצב שמכילה את כל הנתונים במיקום הזה, כולל נתוני הצאצאים. אם אין נתונים, תמונת המצב שמוחזרת היא null.
בדוגמה הבאה אפשר לראות איך משחק מאחזר את הניקוד של טבלת המובילים ממסד הנתונים:
FirebaseDatabase.DefaultInstance .GetReference("Leaders") .ValueChanged += HandleValueChanged; } void HandleValueChanged(object sender, ValueChangedEventArgs args) { if (args.DatabaseError != null) { Debug.LogError(args.DatabaseError.Message); return; } // Do something with the data in args.Snapshot }
ValueChangedEventArgs מכיל DataSnapshot שמכיל את הנתונים במיקום שצוין במסד הנתונים בזמן האירוע. קריאה ל-Value בתמונת מצב מחזירה Dictionary<string, object> שמייצג את הנתונים.
אם אין נתונים במיקום, קריאה ל-Value מחזירה את הערך null.
בדוגמה הזו, נבדק גם args.DatabaseError כדי לראות אם הקריאה בוטלה. לדוגמה, פעולת קריאה יכולה להתבטל אם ללקוח אין הרשאה לקרוא ממיקום של מסד נתונים ב-Firebase. השדה DatabaseError יציין את הסיבה לכך שהאימות נכשל.
בהמשך אפשר לבטל את ההרשמה לאירוע באמצעות כל DatabaseReference עם אותו נתיב. מופעי DatabaseReference הם זמניים, ואפשר להתייחס אליהם כדרך לגשת לכל נתיב ושאילתה.
FirebaseDatabase.DefaultInstance .GetReference("Leaders") .ValueChanged -= HandleValueChanged; // unsubscribe from ValueChanged. }
אירועים משניים
אירועים משניים מופעלים בתגובה לפעולות ספציפיות שמתרחשות בצאצאים של צומת, כמו הוספת צאצא חדש באמצעות השיטה Push() או עדכון של צאצא באמצעות השיטה UpdateChildrenAsync(). כל אחד מהם יכול להיות שימושי להאזנה לשינויים בצומת ספציפי במסד נתונים. לדוגמה, במשחק מסוים אפשר להשתמש בשיטות האלה ביחד כדי לעקוב אחרי הפעילות בתגובות של סשן משחק, כמו שמוצג בהמשך:
var ref = FirebaseDatabase.DefaultInstance .GetReference("GameSessionComments"); ref.ChildAdded += HandleChildAdded; ref.ChildChanged += HandleChildChanged; ref.ChildRemoved += HandleChildRemoved; ref.ChildMoved += HandleChildMoved; } void HandleChildAdded(object sender, ChildChangedEventArgs args) { if (args.DatabaseError != null) { Debug.LogError(args.DatabaseError.Message); return; } // Do something with the data in args.Snapshot } void HandleChildChanged(object sender, ChildChangedEventArgs args) { if (args.DatabaseError != null) { Debug.LogError(args.DatabaseError.Message); return; } // Do something with the data in args.Snapshot } void HandleChildRemoved(object sender, ChildChangedEventArgs args) { if (args.DatabaseError != null) { Debug.LogError(args.DatabaseError.Message); return; } // Do something with the data in args.Snapshot } void HandleChildMoved(object sender, ChildChangedEventArgs args) { if (args.DatabaseError != null) { Debug.LogError(args.DatabaseError.Message); return; } // Do something with the data in args.Snapshot }
האירוע ChildAdded משמש בדרך כלל לאחזור רשימה של פריטים במסד נתונים של Firebase. האירוע ChildAdded מופעל פעם אחת לכל צאצא קיים, ואז שוב בכל פעם שנוסף צאצא חדש לנתיב שצוין. המאזין מקבל תמונת מצב שמכילה את הנתונים של הצאצא החדש.
האירוע ChildChanged מופעל בכל פעם שצומת צאצא משתנה.
זה כולל כל שינוי בצאצאים של צומת הצאצא. בדרך כלל משתמשים בו בשילוב עם האירועים ChildAdded ו-ChildRemoved כדי להגיב לשינויים ברשימת פריטים. תמונת המצב שמועברת לרכיב event listener מכילה את הנתונים המעודכנים של הצאצא.
האירוע ChildRemoved מופעל כשמסירים צאצא מיידי.
בדרך כלל משתמשים בו בשילוב עם פונקציות ה-callback ChildAdded ו-ChildChanged. תמונת המצב שמועברת לקריאה החוזרת (callback) של האירוע מכילה את הנתונים של הצאצא שהוסר.
האירוע ChildMoved מופעל בכל פעם שהאירוע ChildChanged מופעל על ידי עדכון שגורם לשינוי הסדר של הצאצא. הוא משמש לנתונים שמסודרים לפי OrderByChild או OrderByValue.
מיון וסינון נתונים
אפשר להשתמש במחלקה Realtime Database Query כדי לאחזר נתונים שממוינים לפי מפתח, לפי ערך או לפי ערך של צאצא. אפשר גם לסנן את התוצאה הממוינת למספר ספציפי של תוצאות או לטווח של מפתחות או ערכים.
מיון נתונים
כדי לאחזר נתונים ממוינים, קודם צריך לציין את אחת משיטות הסידור כדי לקבוע איך התוצאות יסודרו:
| שיטה | שימוש |
|---|---|
OrderByChild() |
סידור התוצאות לפי הערך של מפתח צאצא שצוין. |
OrderByKey()
| סידור התוצאות לפי מפתחות צאצא. |
OrderByValue() |
סידור התוצאות לפי ערכי הצאצאים. |
אפשר להשתמש רק בשיטת סידור אחת בכל פעם. אם קוראים לשיטת הסידור כמה פעמים באותה שאילתה, מתקבלת שגיאה.
בדוגמה הבאה אפשר לראות איך נרשמים לטבלת ניקוד שממוינת לפי ניקוד.
FirebaseDatabase.DefaultInstance .GetReference("Leaders").OrderByChild("score") .ValueChanged += HandleValueChanged; } void HandleValueChanged(object sender, ValueChangedEventArgs args) { if (args.DatabaseError != null) { Debug.LogError(args.DatabaseError.Message); return; } // Do something with the data in args.Snapshot }
הקוד הזה מגדיר שאילתה שכאשר משלבים אותה עם רכיב event listener מסוג valuechanged, היא מסנכרנת את הלקוח עם טבלת המובילים במסד הנתונים, לפי הניקוד של כל רשומה. במאמר Structure Your Database תוכלו לקרוא מידע נוסף על בניית מבנה יעיל לנתונים.
הקריאה ל-method OrderByChild() מציינת את מפתח הצאצא שלפיו יסודרו התוצאות. במקרה הזה, התוצאות ממוינות לפי הערך של "score" בכל צאצא. במאמר איך מסודרים נתוני השאילתה מוסבר איך מסודרים סוגי נתונים אחרים.
סינון נתונים
כדי לסנן נתונים, אפשר לשלב כל אחת משיטות ההגבלה או הטווח עם שיטת הסידור כשיוצרים שאילתה.
| שיטה | שימוש |
|---|---|
LimitToFirst() |
מגדיר את המספר המקסימלי של פריטים שיוחזרו מתחילת רשימת התוצאות המסודרת. |
LimitToLast() |
מגדירה את המספר המקסימלי של פריטים שיוחזרו מסוף רשימת התוצאות המסודרת. |
StartAt() |
החזרת פריטים שגדולים מהמפתח או מהערך שצוינו או שווים להם, בהתאם לשיטת הסידור שנבחרה. |
EndAt() |
החזרת פריטים שקטנים מהמפתח או מהערך שצוינו או שווים להם, בהתאם לשיטת הסידור שנבחרה. |
EqualTo() |
הפונקציה מחזירה פריטים ששווים למפתח או לערך שצוינו, בהתאם לשיטת הסידור שנבחרה. |
בניגוד לשיטות הסידור, אפשר לשלב כמה פונקציות של הגבלה או טווח.
לדוגמה, אפשר לשלב את השיטות StartAt() ו-EndAt() כדי להגביל את התוצאות לטווח ערכים מסוים.
גם אם יש רק התאמה אחת לשאילתה, תמונת המצב עדיין תהיה רשימה, אבל היא תכיל רק פריט אחד.
להגביל את מספר התוצאות
אפשר להשתמש ב-methods LimitToFirst() ו-LimitToLast() כדי להגדיר את המספר המקסימלי של צאצאים לסנכרון בקריאה חוזרת (callback) נתונה. לדוגמה, אם אתם משתמשים ב-LimitToFirst() כדי להגדיר מגבלה של 100, בהתחלה תקבלו עד 100 קריאות חוזרות (callbacks) של ChildAdded. אם יש פחות מ-100 פריטים במסד הנתונים של Firebase, מופעלת קריאה חוזרת (callback) מסוג ChildAdded לכל פריט.
כשהפריטים משתנים, אתם מקבלים קריאות חוזרות (callbacks) מסוג ChildAdded לפריטים שנכנסים לשאילתה וקריאות חוזרות מסוג ChildRemoved לפריטים שיוצאים ממנה, כך שהמספר הכולל נשאר 100.
לדוגמה, הקוד הבא מחזיר את הניקוד הגבוה ביותר מטבלת המובילים:
FirebaseDatabase.DefaultInstance .GetReference("Leaders").OrderByChild("score").LimitToLast(1) .ValueChanged += HandleValueChanged; } void HandleValueChanged(object sender, ValueChangedEventArgs args) { if (args.DatabaseError != null) { Debug.LogError(args.DatabaseError.Message); return; } // Do something with the data in args.Snapshot }
סינון לפי מפתח או ערך
אתם יכולים להשתמש ב-StartAt(), ב-EndAt() וב-EqualTo() כדי לבחור נקודות התחלה, סיום ושוויון שרירותיות לשאילתות.
האפשרות הזו יכולה להיות שימושית להצגת נתונים בדפים או למציאת פריטים עם צאצאים שיש להם ערך ספציפי.
איך נתוני השאילתות מסודרים
בקטע הזה מוסבר איך הנתונים ממוינים לפי כל אחת משיטות הסידור במחלקה Query.
OrderByChild
כשמשתמשים ב-OrderByChild(), הנתונים שמכילים את מפתח הצאצא שצוין מסודרים באופן הבא:
- ילדים עם ערך
nullלמפתח הצאצא שצוין מופיעים ראשונים. - אחריהם מופיעים צאצאים עם הערך
falseבמפתח הצאצא שצוין. אם לכמה צאצאים יש ערך שלfalse, הם ממוינים לקסיקוגרפית לפי מפתח. - אחריהם מופיעים צאצאים עם הערך
trueבמפתח הצאצא שצוין. אם לכמה צאצאים יש ערך שלtrue, הם ממוינים לפי סדר לקסיקוגרפי לפי מפתח. - אחריהם מופיעים צאצאים עם ערך מספרי, בסדר עולה. אם לכמה צאצאים יש אותו ערך מספרי בצומת הצאצא שצוין, הם ממוינים לפי מפתח.
- מחרוזות מופיעות אחרי מספרים וממוינות בסדר לקסיקוגרפי עולה. אם לכמה צאצאים יש את אותו ערך בצומת הצאצא שצוין, הם מסודרים לפי סדר לקסיקוגרפי לפי מפתח.
- האובייקטים מופיעים בסוף וממוינים בסדר לקסיקוגרפי לפי מפתח בסדר עולה.
OrderByKey
כשמשתמשים ב-OrderByKey() כדי למיין את הנתונים, הנתונים מוחזרים בסדר עולה לפי מפתח.
- הצאצאים עם מפתח שאפשר לנתח כמספר שלם של 32 ביט מופיעים קודם, בסדר עולה.
- אחריהם מופיעים צאצאים עם ערך מחרוזת כמפתח, ממוינים בסדר לקסיקוגרפי עולה.
OrderByValue
כשמשתמשים ב-OrderByValue(), הצאצאים מסודרים לפי הערך שלהם. הקריטריונים לסידור זהים לאלה של OrderByChild(), אבל נעשה שימוש בערך של הצומת במקום בערך של מפתח צאצא שצוין.