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

אחזור של הפניה למסד נתונים

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

Web

import { getDatabase } from "firebase/database";

const database = getDatabase();

Web

var database = firebase.database();

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

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

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

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

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

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

Web

import { getDatabase, ref, push, set } from "firebase/database";

// Create a new post reference with an auto-generated id
const db = getDatabase();
const postListRef = ref(db, 'posts');
const newPostRef = push(postListRef);
set(newPostRef, {
    // ...
});

Web

// Create a new post reference with an auto-generated id
var postListRef = firebase.database().ref('posts');
var newPostRef = postListRef.push();
newPostRef.set({
    // ...
});

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

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

אירוע שימוש רגיל
child_added אחזור רשימות של פריטים או האזנה להוספות לרשימת פריטים. האירוע הזה מופעל פעם אחת לכל צאצא קיים, ואז בכל פעם שמתווסף צאצא חדש לנתיב שצוין. למאזין מועברת קובץ snapshot שמכיל את הנתונים של הצאצא החדש.
child_changed מאזינים לשינויים בפריטים שברשימה. האירוע הזה מופעל בכל פעם שצומת צאצא משתנה. זה כולל כל שינוי בצאצאים של צומת הצאצא. תמונת המצב שמועברת למאזין האירועים מכילה את הנתונים המעודכנים של הצאצא.
child_removed האזנה לפריטים שמוסרים מרשימת פריטים. האירוע הזה מופעל כשמסירים צאצא מיידי.תמונת המצב שמועברת לבלוק הקריאה החוזרת מכילה את הנתונים של הילד או הילדה שהוסר.
child_moved מאזינים לשינויים בסדר הפריטים ברשימה ממוינת. אירועי child_moved תמיד מופיעים אחרי אירוע child_changed שגרם לשינוי הסדר של הפריט (על סמך שיטת הסדר הנוכחית).

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

Web

import { getDatabase, ref, onChildAdded, onChildChanged, onChildRemoved } from "firebase/database";

const db = getDatabase();
const commentsRef = ref(db, 'post-comments/' + postId);
onChildAdded(commentsRef, (data) => {
  addCommentElement(postElement, data.key, data.val().text, data.val().author);
});

onChildChanged(commentsRef, (data) => {
  setCommentValues(postElement, data.key, data.val().text, data.val().author);
});

onChildRemoved(commentsRef, (data) => {
  deleteComment(postElement, data.key);
});

Web

var commentsRef = firebase.database().ref('post-comments/' + postId);
commentsRef.on('child_added', (data) => {
  addCommentElement(postElement, data.key, data.val().text, data.val().author);
});

commentsRef.on('child_changed', (data) => {
  setCommentValues(postElement, data.key, data.val().text, data.val().author);
});

commentsRef.on('child_removed', (data) => {
  deleteComment(postElement, data.key);
});

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

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

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

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

Web

import { getDatabase, ref, onValue } from "firebase/database";

const db = getDatabase();
const dbRef = ref(db, '/a/b/c');

onValue(dbRef, (snapshot) => {
  snapshot.forEach((childSnapshot) => {
    const childKey = childSnapshot.key;
    const childData = childSnapshot.val();
    // ...
  });
}, {
  onlyOnce: true
});

Web

ref.once('value', (snapshot) => {
  snapshot.forEach((childSnapshot) => {
    var childKey = childSnapshot.key;
    var childData = childSnapshot.val();
    // ...
  });
});

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

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

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

מיון נתונים

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

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

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

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

Web

import { getDatabase, ref, query, orderByChild } from "firebase/database";
import { getAuth } from "firebase/auth";

const db = getDatabase();
const auth = getAuth();

const myUserId = auth.currentUser.uid;
const topUserPostsRef = query(ref(db, 'user-posts/' + myUserId), orderByChild('starCount'));

Web

var myUserId = firebase.auth().currentUser.uid;
var topUserPostsRef = firebase.database().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().

Web

import { getDatabase, ref, query, orderByChild } from "firebase/database";

const db = getDatabase();
const mostViewedPosts = query(ref(db, 'posts'), orderByChild('metrics/views'));

Web

var mostViewedPosts = firebase.database().ref('posts').orderByChild('metrics/views');

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

סינון נתונים

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

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

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

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

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

כשהפריטים משתנים, אתם מקבלים אירועי child_added על פריטים שמתווספים לשאילתה ואירועי child_removed על פריטים שיוצאים ממנה, כך שהמספר הכולל נשאר 100.

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

Web

import { getDatabase, ref, query, limitToLast } from "firebase/database";

const db = getDatabase();
const recentPostsRef = query(ref(db, 'posts'), limitToLast(100));

Web

var recentPostsRef = firebase.database().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.

השלבים הבאים