עבודה עם רשימות נתונים

קבלת הפניה למסד נתונים

כדי לקרוא או לכתוב נתונים ממסד הנתונים, צריך מופע של DatabaseReference:

DatabaseReference ref = FirebaseDatabase.instance.ref();

קריאה וכתיבה של רשימות

הוספה לרשימה של נתונים

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

אפשר להשתמש בהפניה לנתונים החדשים שמוחזרים באמצעות השיטה push() כדי לקבל הערך של המפתח שנוצר באופן אוטומטי על ידי הילד או הילדה או של הנתונים שהגדרתם. המאפיין .key של הפניה push() מכיל את המפתח שנוצר באופן אוטומטי.

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

לדוגמה, אפשר להשתמש ב-push() כדי להוסיף פוסט חדש לרשימת פוסטים באפליקציה חברתית:

DatabaseReference postListRef = FirebaseDatabase.instance.ref("posts");
DatabaseReference newPostRef = postListRef.push();
newPostRef.set({
  // ...
});

האזנה לאירועים משוכפלים

אירועי הצאצאים מופעלים בתגובה לפעולות ספציפיות שקורות לצאצאים של צומת מפעולה, כמו צאצא חדש שנוסף באמצעות השיטה push() או צאצא שמתעדכן באמצעות השיטה update().

אירוע שימוש אופייני
onChildAdded אחזור רשימות של פריטים או האזנה להוספות לרשימת פריטים. האירוע הזה מופעל פעם אחת לכל צאצא קיים ואז שוב בכל פעם שצאצא חדש נוסף לנתיב שצוין. המאזינים הם העבירה תמונת מצב שמכילה את הנתונים של הילד או הילדה החדש.
onChildChanged האזנה לשינויים בפריטים ברשימה. האירוע הזה מופעל בכל פעם שצומת צאצא משתנה. זה כולל כל שינוי בצאצאים של צומת הצאצא. תמונת המצב (snapshot) שמועברת למאזין האירועים מכילה את הנתונים המעודכנים של הצאצא.
onChildRemoved האזנה לפריטים שהוסרו מרשימה. האירוע הזה מופעל כאשר צאצא מיידי יוסר.תמונת המצב שמועברת לבלוק הקריאה החוזרת (callback) מכילה את הנתונים של הילד או הילדה שהוסרו.
onChildMoved האזנה לשינויים בסדר הפריטים ברשימה מסודרת. אירועי onChildmigrate תמיד מופיעים לפי אירוע onChildChanged שגרם להזמנת הפריט (על סמך השיטה הנוכחית של סידור לפי).

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

final commentsRef = FirebaseDatabase.instance.ref("post-comments/$postId");
commentsRef.onChildAdded.listen((event) {
  // A new comment has been added, so add it to the displayed list.
});
commentsRef.onChildChanged.listen((event) {
  // A comment has changed; use the key to determine if we are displaying this
  // comment and if so displayed the changed comment.
});
commentsRef.onChildRemoved.listen((event) {
  // A comment has been removed; use the key to determine if we are displaying
  // this comment and if so remove it.
});

האזנה לאירועי ערך

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

צירוף של מאזין value לרשימה של נתונים יחזיר את כל רשימת הנתונים כתמונת מצב אחת, שאפשר יהיה להריץ בלולאה כדי לגשת לצאצאים ספציפיים.

גם אם יש רק התאמה אחת לשאילתה, קובץ snapshot עדיין יהיה רשימה, רק שהוא יכיל פריט אחד. כדי לגשת לפריט, צריך להריץ לולאה על התוצאה:

myTopPostsQuery.onValue.listen((event) {
  for (final child in event.snapshot.children) {
    // Handle the post.
  }
}, onError: (error) {
  // Error.
});

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

מיון וסינון של נתונים

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

מיון נתונים

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

שיטה שימוש
orderByChild() סדר התוצאות לפי הערך של מפתח צאצא שצוין או של נתיב צאצא מקונן.
orderByKey() אפשר לסדר את התוצאות לפי מפתחות צאצא.
orderByValue() מיון התוצאות לפי ערכי הצאצאים.

אפשר להשתמש רק בשיטה אחת לסדר לפי בכל פעם. קריאה ל-method מסוג order-by מספר פעמים באותה שאילתה תגרום לשגיאה.

הדוגמה הבאה ממחישה איך אפשר לאחזר רשימה של פוסטים מובילים ממוינים לפי מספר הכוכבים שלהם:

final myUserId = FirebaseAuth.instance.currentUser?.uid;
final topUserPostsRef = FirebaseDatabase.instance
    .ref("user-posts/$myUserId")
    .orderByChild("starCount");

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

הקריאה ל-method orderByChild() מציינת את מפתח הצאצא כדי להזמין את תוצאות ב-. במקרה כזה, הפוסטים ממוינים לפי הערך של הצאצא "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 על ידי ציון הנתיב היחסי לצאצא המוטמע בקריאה ל-orderByChild().

final mostViewedPosts =
    FirebaseDatabase.instance.ref('posts').orderByChild('metrics/views');

מידע נוסף על סדר של סוגים אחרים של נתונים זמין במאמר איך מתבצע הסדר של נתוני השאילתות.

סינון נתונים

כדי לסנן נתונים, אפשר לשלב כל אחת מהשיטות של limit או range עם שיטת order-by כשיוצרים שאילתה.

שיטה שימוש
limitToFirst() מגדיר את המספר המקסימלי של פריטים להחזרה מתחילת רשימת התוצאות הממוזערת.
limitToLast() מגדיר את המספר המקסימלי של פריטים להחזרה מסוף רשימת התוצאות הממוזערת.
startAt() הפונקציה מחזירה פריטים שגדולים או שווים למפתח או לערך שצוינו, בהתאם לשיטת הסדר שנבחרה.
startAfter() הפונקציה מחזירה פריטים שגדולים מהמפתח או מהערך שצוינו, בהתאם לשיטת הסדר שנבחרה.
endAt() החזרת פריטים ששווה למפתח או לערך שצוינו או שווים לו, בהתאם לשיטה שבחרתם כדי לסדר את ההודעות.
endBefore() הפונקציה מחזירה פריטים שערכם קטן מהמפתח או מהערך שצוינו, בהתאם לשיטת הסדר שנבחרה.
equalTo() הפונקציה מחזירה פריטים שווים למפתח או לערך שצוינו, בהתאם לשיטת הסדר שנבחרה.

בשונה מהשיטה 'סידור לפי שיטות', כאן אפשר לשלב מספר פונקציות של מגבלה או טווח. לדוגמה, אפשר לשלב את השיטות startAt() ו-endAt() כדי להגביל את התוצאות לטווח ערכים מסוים.

הגבלת מספר התוצאות

אפשר להשתמש ב-methods limitToFirst() ו-limitToLast() כדי להגדיר המספר המקסימלי של צאצאים שיסונכרנו לאירוע נתון. לדוגמה, אם משתמשים ב-limitToFirst() כדי להגדיר מגבלה של 100 פעמים, בהתחלה מקבלים ל-100 אירועי onChildAdded. אם יש לכם פחות מ-100 פריטים שמאוחסנים מסד הנתונים של Firebase, אירוע onChildAdded מופעל לכל פריט.

כשפריטים משתנים, מקבלים אירועים של onChildAdded על פריטים שנכנסים אל ו-onChildRemoved אירועים של פריטים שמפסיקים להשתמש בהם, והמספר הכולל של השהייה הוא 100.

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

final recentPostsRef = FirebaseDatabase.instance.ref('posts').limitToLast(100);

הדוגמה הזו מגדירה רק שאילתה, כדי לסנכרן בפועל נתונים שהיא צריכה מצורף למכשיר האזנה.

סינון לפי מפתח או ערך

אפשר להשתמש ב-startAt(),‏ startAfter(),‏ endAt(),‏ endBefore() ו-equalTo() כדי לבחור נקודות שרירותיות של התחלה, סיום ודומות לשאילתות. האפשרות הזו יכולה להיות שימושית לחלוקת נתונים לדפים או לאיתור פריטים עם צאצאים שיש להם ערך ספציפי.

איך מסודרים נתוני שאילתות

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

orderByChild

כשמשתמשים ב-orderByChild(), נתונים שמכילים את מפתח הצאצא שצוין הם מסודרות כך:

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

orderByKey

כשמשתמשים ב-orderByKey() כדי למיין את הנתונים, הנתונים מוחזרים בסדר עולה לפי מפתח.

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

orderByValue

כשמשתמשים ב-orderByValue(), הילדים מסודרים לפי הערך שלהם. קריטריונים הסדר זהים לקריטריונים של orderByChild(), אלא שהערך של הצומת משמש במקום הערך של מפתח צאצא שצוין.

ניתוק של רכיבי מעקב

כדי להסיר קריאות חוזרות, קוראים ל-method‏ off() במזהה של מסד הנתונים ב-Firebase.

כדי להסיר מאזין יחיד, מעבירים אותו כפרמטר ל-off(). קריאה ל-off() במיקום ללא ארגומנטים תגרום להסרה של כל המאזינים מאותו מיקום המיקום.

קריאה ל-off() על מאזין הורה לא מסירה באופן אוטומטי מאזינים שרשומים בצמתים הצאצאים שלו. צריך לקרוא ל-off() גם על כל מאזיני הצאצאים כדי להסיר את פונקציית ה-callback.

השלבים הבאים