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

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

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

איך מובנים נתונים: זה עץ JSON

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

אם אתה יוצר מפתחות משלך, הם צריכים להיות בקידוד UTF-8, יכול להיות מקסימום של 768 בתים, ולא יכולים להכיל . , $ , # , [ , ] , / , או תווי בקרה ASCII 0-31 או 127. אתה לא יכול להשתמש תווי בקרה ASCII בערכים עצמם, או.

לדוגמה, שקול יישום צ'אט המאפשר למשתמשים לאחסן פרופיל בסיסי ורשימת אנשי קשר. פרופיל משתמש טיפוסי ממוקם נתיב, כגון /users/$uid . המשתמש alovelace שאולי יש ערך מסד נתונים שנראה בערך ככה:

{
  "users": {
    "alovelace": {
      "name": "Ada Lovelace",
      "contacts": { "ghopper": true },
    },
    "ghopper": { ... },
    "eclarke": { ... }
  }
}

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

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

הימנע מקינון נתונים

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

לדוגמא מדוע נתונים מקוננים אינם טובים, שקול את המבנה המקונן המקונן הבא:

{
  // This is a poorly nested data architecture, because iterating the children
  // of the "chats" node to get a list of conversation titles requires
  // potentially downloading hundreds of megabytes of messages
  "chats": {
    "one": {
      "title": "Historical Tech Pioneers",
      "messages": {
        "m1": { "sender": "ghopper", "message": "Relay malfunction found. Cause: moth." },
        "m2": { ... },
        // a very long list of messages
      }
    },
    "two": { ... }
  }
}

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

שטחו את מבני הנתונים

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

{
  // Chats contains only meta info about each conversation
  // stored under the chats's unique ID
  "chats": {
    "one": {
      "title": "Historical Tech Pioneers",
      "lastMessage": "ghopper: Relay malfunction found. Cause: moth.",
      "timestamp": 1459361875666
    },
    "two": { ... },
    "three": { ... }
  },

  // Conversation members are easily accessible
  // and stored by chat conversation ID
  "members": {
    // we'll talk about indices like this below
    "one": {
      "ghopper": true,
      "alovelace": true,
      "eclarke": true
    },
    "two": { ... },
    "three": { ... }
  },

  // Messages are separate from data we may want to iterate quickly
  // but still easily paginated and queried, and organized by chat
  // conversation ID
  "messages": {
    "one": {
      "m1": {
        "name": "eclarke",
        "message": "The relay seems to be malfunctioning.",
        "timestamp": 1459361875337
      },
      "m2": { ... },
      "m3": { ... }
    },
    "two": { ... },
    "three": { ... }
  }
}

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

צור נתונים המשתנים

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

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

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

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

// An index to track Ada's memberships
{
  "users": {
    "alovelace": {
      "name": "Ada Lovelace",
      // Index Ada's groups in her profile
      "groups": {
         // the value here doesn't matter, just that the key exists
         "techpioneers": true,
         "womentechmakers": true
      }
    },
    ...
  },
  "groups": {
    "techpioneers": {
      "name": "Historical Tech Pioneers",
      "members": {
        "alovelace": true,
        "ghopper": true,
        "eclarke": true
      }
    },
    ...
  }
}

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

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

גישה זו, היפוך הנתונים על ידי הוספת המזהים כמפתחות הגדרת הערך אמיתי, עושה בדיקת מפתח פשוט כמו קריאה /users/$uid/groups/$group_id ובדיקה אם הוא null . האינדקס מהיר יותר ויעיל יותר מאשר שאילתות או סריקת נתונים.

הצעדים הבאים