קבלת FIRDatabaseReference
כדי לקרוא או לכתוב נתונים במסד הנתונים, צריך מופע של FIRDatabaseReference:
Swift
var ref: DatabaseReference! ref = Database.database().reference()
Objective-C
@property (strong, nonatomic) FIRDatabaseReference *ref; self.ref = [[FIRDatabase database] reference];
קריאה וכתיבה של רשימות
הוספה לרשימת נתונים
משתמשים בשיטה childByAutoId כדי לצרף נתונים לרשימה באפליקציות מרובות משתמשים. השיטה childByAutoId יוצרת מפתח ייחודי בכל פעם שמוסיפים צאצא חדש להפניה שצוינה ב-Firebase. באמצעות המפתחות האלה שנוצרים אוטומטית לכל רכיב חדש ברשימה, כמה לקוחות יכולים להוסיף צאצאים לאותו מיקום בו-זמנית בלי שיהיו התנגשויות בכתיבה. המפתח הייחודי שנוצר על ידי childByAutoId מבוסס על חותמת זמן, כך שפריטים ברשימה מסודרים אוטומטית בסדר כרונולוגי.
אפשר להשתמש בהפניה לנתונים החדשים שמוחזרים על ידי השיטה childByAutoId כדי לקבל את הערך של המפתח שנוצר אוטומטית של צאצא או להגדיר נתונים לצאצא. קריאה ל-getKey בהפניה ל-childByAutoId מחזירה את המפתח שנוצר אוטומטית.
אתם יכולים להשתמש במפתחות שנוצרו אוטומטית כדי לפשט את תהליך השטחת מבנה הנתונים. מידע נוסף זמין בדוגמה של fan-out נתונים.
האזנה לאירועים משוכפלים
אירועים שקשורים לצאצאים מופעלים בתגובה לפעולות ספציפיות שמתבצעות בצאצאים של צומת מפעולה כמו הוספת צאצא חדש באמצעות השיטה childByAutoId או עדכון צאצא באמצעות השיטה updateChildValues.
| סוג האירוע | שימוש אופייני |
|---|---|
FIRDataEventTypeChildAdded |
אחזור רשימות של פריטים או האזנה להוספות לרשימה של פריטים. האירוע הזה מופעל פעם אחת לכל צאצא קיים, ואז שוב בכל פעם שמוסיפים צאצא חדש לנתיב שצוין. המאזין מקבל תמונה של מצב הנתונים שמכילה את הנתונים של צאצא חדש. |
FIRDataEventTypeChildChanged |
חיפוש שינויים בפריטים ברשימה. האירוע הזה מופעל בכל פעם שמשנים צומת צאצא. האיסור הזה כולל שינויים בצאצאים של צומת הילד. תמונת המצב שמועברת לרכיב event listener מכילה את הנתונים המעודכנים של צאצא. |
FIRDataEventTypeChildRemoved |
האזנה להסרה של פריטים מרשימה. האירוע הזה מופעל כשמסירים צאצא מיידי.ה-snapshot שמועבר לבלוק של פונקציית הקריאה החוזרת מכיל את הנתונים של הצאצא שהוסר. |
FIRDataEventTypeChildMoved |
האזנה לשינויים בסדר של פריטים ברשימה ממוספרת.
האירוע הזה מופעל בכל פעם שעדכון גורם לסידור מחדש של הילד. הוא משמש עם נתונים שמסודרים לפי queryOrderedByChild
או queryOrderedByValue.
|
כל אחת מהשיטות האלה יכולה להיות שימושית למעקב אחרי שינויים בצומת ספציפי במסד נתונים. לדוגמה, אפליקציה לבלוגים ברשתות חברתיות יכולה להשתמש בשיטות האלה יחד כדי לעקוב אחרי הפעילות בתגובות של פוסט, כמו שמוצג בהמשך:
Swift
// Listen for new comments in the Firebase database commentsRef.observe(.childAdded, with: { (snapshot) -> Void in self.comments.append(snapshot) self.tableView.insertRows( at: [IndexPath(row: self.comments.count - 1, section: self.kSectionComments)], with: UITableView.RowAnimation.automatic ) }) // Listen for deleted comments in the Firebase database commentsRef.observe(.childRemoved, with: { (snapshot) -> Void in let index = self.indexOfMessage(snapshot) self.comments.remove(at: index) self.tableView.deleteRows( at: [IndexPath(row: index, section: self.kSectionComments)], with: UITableView.RowAnimation.automatic ) })
Objective-C
// Listen for new comments in the Firebase database [_commentsRef observeEventType:FIRDataEventTypeChildAdded withBlock:^(FIRDataSnapshot *snapshot) { [self.comments addObject:snapshot]; [self.tableView insertRowsAtIndexPaths:@[ [NSIndexPath indexPathForRow:self.comments.count - 1 inSection:kSectionComments] ] withRowAnimation:UITableViewRowAnimationAutomatic]; }]; // Listen for deleted comments in the Firebase database [_commentsRef observeEventType:FIRDataEventTypeChildRemoved withBlock:^(FIRDataSnapshot *snapshot) { int index = [self indexOfMessage:snapshot]; [self.comments removeObjectAtIndex:index]; [self.tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:index inSection:kSectionComments]] withRowAnimation:UITableViewRowAnimationAutomatic]; }];
המתנה לאירועי ערך
הדרך המומלצת לקרוא רשימות של נתונים היא להאזין לאירועי צאצא, אבל יש מצבים שבהם כדאי להאזין לאירועי ערך בהפניה לרשימה.
צירוף של FIRDataEventTypeValue observer לרשימת נתונים יחזיר את כל רשימת הנתונים כ-DataSnapshot יחיד, שאפשר להשתמש בו בלולאה כדי לגשת לנתונים של ילדים בודדים.
גם אם יש רק התאמה אחת לשאילתה, התמונה היא עדיין רשימה, רק שהיא מכילה פריט אחד. כדי לגשת לפריט, צריך להשתמש בלולאה כדי לעבור על התוצאה:
Swift
_commentsRef.observe(.value) { snapshot in for child in snapshot.children { ... } }
Objective-C
[_commentsRef observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) { // Loop over children NSEnumerator *children = [snapshot children]; FIRDataSnapshot *child; while (child = [children nextObject]) { // ... } }];
הדפוס הזה יכול להיות שימושי כשרוצים לאחזר את כל הצאצאים של רשימה בפעולה אחת, במקום להאזין לאירועים נוספים של הוספת צאצא.
מיון וסינון של נתונים
אפשר להשתמש במחלקת Realtime Database FIRDatabaseQuery כדי לאחזר נתונים ממוינים לפי מפתח, לפי ערך או לפי הערך של צאצא. אפשר גם לסנן את התוצאה הממוינת למספר מסוים של תוצאות או לטווח של מפתחות או ערכים.
מיון נתונים
כדי לאחזר נתונים ממוינים, צריך קודם לציין אחת משיטות המיון כדי לקבוע את סדר התוצאות:
| שיטה | שימוש |
|---|---|
queryOrderedByKey
| ממיינים את התוצאות לפי מפתחות צאצא. |
queryOrderedByValue |
מיון התוצאות לפי ערכי הצאצא. |
queryOrderedByChild |
מיון התוצאות לפי הערך של מפתח צאצא ספציפי או נתיב צאצא מוטמע. |
אפשר להשתמש רק בשיטת מיון אחת בכל פעם. הפעלת שיטה של מיון לפי סדר (order-by) מספר פעמים באותה שאילתה גורמת לשגיאה.
בדוגמה הבאה אפשר לראות איך מאחזרים רשימה של הפוסטים המובילים של משתמש, ממוינים לפי מספר הכוכבים:
Swift
// My top posts by number of stars let myTopPostsQuery = ref.child("user-posts").child(getUid()).queryOrdered(byChild: "starCount")
Objective-C
// My top posts by number of stars FIRDatabaseQuery *myTopPostsQuery = [[[self.ref child:@"user-posts"] child:[super getUid]] queryOrderedByChild:@"starCount"];
השאילתה הזו מאחזרת את הפוסטים של המשתמש מהנתיב במסד הנתונים על סמך מזהה המשתמש, ומסדרת אותם לפי מספר הכוכבים שכל פוסט קיבל. הטכניקה הזו של שימוש במזהים כמפתחות אינדקס נקראת פיצול נתונים. אפשר לקרוא עליה עוד במאמר Structure Your Database (ארגון מסד הנתונים).
הקריאה לשיטה queryOrderedByChild מציינת את מפתח הצאצא למיון התוצאות. בדוגמה הזו, הפוסטים ממוינים לפי הערך של הצאצא "starCount" בכל פוסט. אפשר גם למיין שאילתות לפי צאצאים מקוננים, אם יש לכם נתונים שנראים כך:
"posts": {
"ts-functions": {
"metrics": {
"views" : 1200000,
"likes" : 251000,
"shares": 1200,
},
"title" : "Why you should use TypeScript for writing Cloud Functions",
"author": "Doug",
},
"android-arch-3": {
"metrics": {
"views" : 900000,
"likes" : 117000,
"shares": 144,
},
"title" : "Using Android Architecture Components with Firebase Realtime Database (Part 3)",
"author": "Doug",
}
},במקרה כזה, אנחנו יכולים להזמין את רכיבי הרשימה לפי ערכים שמוטמעים מתחת למפתח metrics על ידי ציון הנתיב היחסי לצאצא המוטמע בקריאה queryOrderedByChild.
Swift
let postsByMostPopular = ref.child("posts").queryOrdered(byChild: "metrics/views")
Objective-C
FIRDatabaseQuery *postsByMostPopular = [[ref child:@"posts"] queryOrderedByChild:@"metrics/views"];
מידע נוסף על סדר הנתונים של סוגי נתונים אחרים זמין במאמר איך מסודרים הנתונים בשאילתות.
סינון נתונים
כדי לסנן נתונים, אפשר לשלב כל אחת מהשיטות של הגבלה או טווח עם שיטת מיון כשיוצרים שאילתה.
| שיטה | שימוש |
|---|---|
queryLimitedToFirst |
מגדיר את המספר המקסימלי של פריטים שיוחזרו מתחילת הרשימה הממוינת של התוצאות. |
queryLimitedToLast |
מגדיר את המספר המקסימלי של פריטים שיוחזרו מסוף הרשימה הממוינת של התוצאות. |
queryStartingAtValue |
הפונקציה מחזירה פריטים שגדולים מהמפתח או מהערך שצוינו או שווים להם, בהתאם לשיטת המיון שנבחרה. |
queryStartingAfterValue |
החזרת פריטים שגדולים מהמפתח או מהערך שצוינו, בהתאם לשיטת המיון שנבחרה. |
queryEndingAtValue |
הפונקציה מחזירה פריטים שקטנים מהמפתח או מהערך שצוינו או שווים להם, בהתאם לשיטת המיון שנבחרה. |
queryEndingBeforeValue |
הפונקציה מחזירה פריטים עם ערך נמוך מהמפתח או מהערך שצוינו, בהתאם לשיטה שנבחרה למיון. |
queryEqualToValue |
הפונקציה מחזירה פריטים ששווים למפתח או לערך שצוינו, בהתאם לשיטת המיון שנבחרה. |
בניגוד לשיטות order-by, אפשר לשלב כמה פונקציות limit או range.
לדוגמה, אפשר לשלב בין השיטות queryStartingAtValue ו-queryEndingAtValue כדי להגביל את התוצאות לטווח ערכים מסוים.
הגבלת מספר התוצאות
אפשר להשתמש בשיטות queryLimitedToFirst ו-queryLimitedToLast כדי להגדיר מספר מקסימלי של צאצאים שיסונכרנו עבור קריאה חוזרת (callback) נתונה. לדוגמה, אם משתמשים ב-queryLimitedToFirst כדי להגדיר מגבלה של 100, מקבלים בהתחלה רק עד 100 קריאות חוזרות מסוג FIRDataEventTypeChildAdded. אם יש פחות מ-100 פריטים שמאוחסנים במסד הנתונים של Firebase, מופעלת קריאה חוזרת מסוג FIRDataEventTypeChildAdded לכל פריט.
כשהפריטים משתנים, מקבלים קריאות חוזרות (callback) מסוג FIRDataEventTypeChildAdded לפריטים שנכנסים לשאילתה וקריאות חוזרות מסוג FIRDataEventTypeChildRemoved לפריטים שיוצאים ממנה, כך שהמספר הכולל נשאר 100.
בדוגמה הבאה אפשר לראות איך אפליקציה לדוגמה לניהול בלוג יכולה לאחזר רשימה של 100 הפוסטים האחרונים של כל המשתמשים:
Swift
// Last 100 posts, these are automatically the 100 most recent // due to sorting by push() keys let recentPostsQuery = (ref?.child("posts").queryLimited(toFirst: 100))!
Objective-C
// Last 100 posts, these are automatically the 100 most recent // due to sorting by push() keys FIRDatabaseQuery *recentPostsQuery = [[self.ref child:@"posts"] queryLimitedToFirst:100];
סינון לפי מפתח או ערך
אפשר להשתמש ב-queryStartingAtValue, queryStartingAfterValue, queryEndingAtValue, queryEndingBeforeValue ו-queryEqualToValue כדי לבחור נקודות שרירותיות להתחלה, לסיום ולשוויון של שאילתות. האפשרות הזו שימושית כשרוצים להוסיף מספור לדפים של נתונים או למצוא פריטים עם צאצאים שיש להם ערך ספציפי.
איך נתוני השאילתות מסודרים
בקטע הזה מוסבר איך הנתונים ממוינים לפי כל אחת מהשיטות של order-by במחלקה FIRDatabaseQuery.
queryOrderedByKey
כשמשתמשים ב-queryOrderedByKey כדי למיין את הנתונים, הנתונים מוחזרים בסדר עולה לפי מפתח.
- הילדים עם מפתח שאפשר לנתח כמספר שלם בן 32 ביט מופיעים ראשונים, בסדר עולה.
- אחריהם מופיעים ילדים עם ערך מחרוזת כמפתח, ממוינים בסדר עולה לפי סדר מילוני.
queryOrderedByValue
כשמשתמשים ב-queryOrderedByValue, הצאצאים מסודרים לפי הערך שלהם. קריטריוני הסדר זהים לאלה של queryOrderedByChild, אלא שהערך של הצומת משמש במקום הערך של מפתח צאצא ספציפי.
queryOrderedByChild
כשמשתמשים ב-queryOrderedByChild, הנתונים שמכילים את מפתח הצאצא שצוין מסודרים באופן הבא:
- ילדים עם ערך
nilלמפתח הילד שצוין מופיעים ראשונים. - אחריהם מופיעים ילדים עם ערך של
falseלמפתח הילד שצוין. אם לכמה צאצאים יש ערך שלfalse, הם ממוינים לקסיקוגרפית לפי מפתח. - אחריהם מופיעים ילדים עם ערך של
trueלמפתח הילד שצוין. אם לכמה צאצאים יש ערך שלtrue, הם ממוינים לפי מפתח בסדר לקסיקוגרפי. - אחריהם מופיעים צאצאים עם ערך מספרי, ממוינים בסדר עולה. אם לכמה צאצאים יש את אותו ערך מספרי בצומת הצאצא שצוין, הם ממוינים לפי מפתח.
- מחרוזות מופיעות אחרי מספרים וממוינות בסדר עולה לפי סדר מילוני. אם לכמה צאצאים יש את אותו ערך בצומת הצאצא שצוין, הם מסודרים לפי סדר מילוני לפי המפתח.
- האובייקטים מופיעים בסוף וממוינים בסדר עולה לפי מפתח, בסדר לקסיקוגרפי.
ניתוק של listeners
הצופים לא מפסיקים אוטומטית את סנכרון הנתונים כשעוזבים את ViewController. אם לא מסירים את האובייקט מסוג Observer בצורה נכונה, הוא ממשיך לסנכרן נתונים לזיכרון המקומי וישמור את כל האובייקטים שנתפסו בסגירת גורם מטפל באירועים, מה שעלול לגרום לדליפות זיכרון. כשכבר לא צריך את האובייקט observer, מסירים אותו על ידי העברת FIRDatabaseHandle המשויך אל השיטה removeObserverWithHandle.
כשמוסיפים בלוק של קריאה חוזרת להפניה, מוחזר FIRDatabaseHandle. אפשר להשתמש בנקודות האחיזה האלה כדי להסיר את בלוק הקריאה החוזרת.
אם נוספו כמה פונקציות listener להפניה למסד נתונים, כל אחת מהן נקראת כשמופעל אירוע. כדי להפסיק את סנכרון הנתונים במיקום מסוים, צריך להסיר את כל הצופים במיקום באמצעות הקריאה לשיטה removeAllObservers.
התקשרות אל removeObserverWithHandle או אל removeAllObservers במאזין לא מסירה באופן אוטומטי מאזינים שרשומים בצמתי הצאצא שלו. צריך גם לעקוב אחרי ההפניות או נקודות האחיזה האלה כדי להסיר אותן.