จัดโครงสร้างฐานข้อมูลของคุณ

ก่อนเริ่มต้น

คุณต้องดำเนินการต่อไปนี้ก่อนจึงจะใช้ Realtime Database, ได้

  • ลงทะเบียนโปรเจ็กต์ Unity และกำหนดค่าให้ใช้ Firebase

    • หากโปรเจ็กต์ Unity ใช้ Firebase อยู่แล้ว แสดงว่าโปรเจ็กต์ได้ลงทะเบียนและกำหนดค่าสำหรับ Firebase แล้ว

    • หากไม่มีโปรเจ็กต์ Unity คุณสามารถดาวน์โหลด แอปตัวอย่างได้

  • เพิ่ม Firebase Unity SDK (โดยเฉพาะ FirebaseDatabase.unitypackage) ลงใน โปรเจ็กต์ Unity

โปรดทราบว่าการเพิ่ม Firebase ลงในโปรเจ็กต์ Unity เกี่ยวข้องกับงานทั้งใน Firebaseคอนโซลและในโปรเจ็กต์ Unity ที่เปิดอยู่ (เช่น คุณดาวน์โหลดไฟล์การกำหนดค่า Firebase จากคอนโซล แล้วย้าย ไฟล์เหล่านั้นไปยังโปรเจ็กต์ Unity)

การจัดโครงสร้างข้อมูล

คู่มือนี้ครอบคลุมแนวคิดหลักบางประการในสถาปัตยกรรมข้อมูลและแนวทางปฏิบัติแนะนำสำหรับการจัดโครงสร้างข้อมูล JSON ใน Firebase Realtime Database

การสร้างฐานข้อมูลที่มีโครงสร้างอย่างเหมาะสมต้องมีการวางแผนล่วงหน้าพอสมควร สิ่งที่สำคัญที่สุดคือคุณต้องวางแผนวิธีบันทึกและดึงข้อมูลในภายหลังเพื่อให้กระบวนการดังกล่าวเป็นไปได้ง่ายที่สุด

วิธีจัดโครงสร้างข้อมูล: เป็นแผนผัง JSON

ระบบจะจัดเก็บข้อมูลทั้งหมดของ Firebase Realtime Database เป็นออบเจ็กต์ JSON คุณสามารถนึกภาพฐานข้อมูลเป็นแผนผัง JSON ที่โฮสต์บนระบบคลาวด์ ซึ่งแตกต่างจากฐานข้อมูล SQL ที่ไม่มีตารางหรือระเบียน เมื่อคุณเพิ่มข้อมูลลงในแผนผัง JSON ข้อมูลนั้นจะกลายเป็นโหนดในโครงสร้าง JSON ที่มีอยู่พร้อมคีย์ที่เชื่อมโยง คุณสามารถระบุคีย์ของคุณเอง เช่น รหัสผู้ใช้หรือชื่อเชิงความหมาย หรือระบบจะระบุคีย์ให้คุณโดยใช้วิธี Push()

ตัวอย่างเช่น ลองพิจารณาแอปพลิเคชันแชทที่อนุญาตให้ผู้ใช้จัดเก็บโปรไฟล์พื้นฐานและข้อมูลรายชื่อติดต่อ โปรไฟล์ผู้ใช้ทั่วไปจะอยู่ในเส้นทาง เช่น /users/$uid ผู้ใช้ alovelace อาจมีรายการฐานข้อมูลลักษณะดังนี้

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

แม้ว่าฐานข้อมูลจะใช้แผนผัง JSON แต่ข้อมูลที่จัดเก็บไว้ในฐานข้อมูลสามารถแสดงเป็นประเภทข้อมูลดั้งเดิมบางประเภทที่สอดคล้องกับประเภท JSON ที่มีอยู่เพื่อช่วยให้คุณเขียนโค้ดที่ดูแลรักษาง่ายขึ้น

แนวทางปฏิบัติแนะนำสำหรับโครงสร้างข้อมูล

หลีกเลี่ยงการซ้อนข้อมูล

เนื่องจาก Firebase Realtime Database อนุญาตให้ซ้อนข้อมูลได้ลึกถึง 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": { "..." }
  }
}

ตอนนี้คุณสามารถวนซ้ำรายการห้องแชทได้โดยการดาวน์โหลดข้อมูลเพียงไม่กี่ไบต์ต่อการสนทนา ซึ่งจะดึงข้อมูลเมตาอย่างรวดเร็วสำหรับการแสดงรายการหรือแสดงห้องแชทใน UI ระบบจะดึงข้อความแยกกันและแสดงเมื่อข้อความมาถึง ซึ่งช่วยให้ UI ตอบสนองและทำงานได้อย่างรวดเร็ว

สร้างข้อมูลที่ปรับขนาดได้

เมื่อสร้างแอป การดาวน์โหลดชุดย่อยของรายการมักจะเป็นวิธีที่ดีกว่า วิธีนี้เป็นวิธีที่ใช้กันโดยทั่วไปหากรายการมีระเบียนหลายพันรายการ เมื่อความสัมพันธ์นี้คงที่และเป็นแบบทางเดียว คุณสามารถซ้อนออบเจ็กต์ลูกไว้ใต้ออบเจ็กต์แม่ได้

บางครั้งความสัมพันธ์นี้อาจมีความเปลี่ยนแปลงมากขึ้น หรืออาจจำเป็นต้องยกเลิกการทำให้ข้อมูลนี้เป็นปกติ หลายครั้งที่คุณสามารถยกเลิกการทำให้ข้อมูลเป็นปกติได้โดยใช้การค้นหา เพื่อดึงข้อมูลชุดย่อย ดังที่อธิบายไว้ใน ดึงข้อมูล

แต่แม้แต่วิธีนี้ก็อาจไม่เพียงพอ ตัวอย่างเช่น ลองพิจารณาความสัมพันธ์แบบ 2 ทางระหว่างผู้ใช้กับกลุ่ม ผู้ใช้สามารถอยู่ในกลุ่มได้ และกลุ่มประกอบด้วยรายชื่อผู้ใช้ เมื่อถึงเวลาตัดสินใจว่าผู้ใช้รายใดอยู่ในกลุ่มใด สิ่งต่างๆ จะซับซ้อนขึ้น

สิ่งที่คุณต้องการคือวิธีที่สวยงามในการแสดงรายการกลุ่มที่ผู้ใช้เป็นสมาชิกและดึงเฉพาะข้อมูลของกลุ่มเหล่านั้น ดัชนีของกลุ่มช่วยได้มากในที่นี้

// 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
      }
    },
    // ...
  }
}

คุณอาจสังเกตเห็นว่าวิธีนี้จะทำซ้ำข้อมูลบางส่วนโดยจัดเก็บความสัมพันธ์ไว้ทั้งในระเบียนของ Ada และในกลุ่ม ตอนนี้ alovelace ได้รับการจัดทำดัชนีภายใต้กลุ่ม และ techpioneers แสดงอยู่ในโปรไฟล์ของ Ada ดังนั้น หากต้องการลบ Ada ออกจากกลุ่ม คุณต้องอัปเดตใน 2 ที่

นี่คือความซ้ำซ้อนที่จำเป็นสำหรับความสัมพันธ์แบบ 2 ทาง ซึ่งช่วยให้คุณ ดึงข้อมูลสมาชิกของ Ada ได้อย่างรวดเร็วและมีประสิทธิภาพ แม้ว่ารายชื่อผู้ใช้หรือ กลุ่มจะขยายเป็นหลายล้านรายการ หรือกฎการรักษาความปลอดภัยของ Realtime Database ป้องกันไม่ให้เข้าถึงระเบียนบางรายการ

แนวทางนี้ ซึ่งเป็นการกลับด้านข้อมูลโดยแสดงรหัสเป็นคีย์และตั้งค่าเป็น "จริง" ทำให้การตรวจสอบคีย์เป็นเรื่องง่ายเพียงแค่การอ่าน /users/$uid/groups/$group_id และตรวจสอบว่าคีย์เป็น null หรือไม่ ดัชนีทำงานได้เร็วกว่าและมีประสิทธิภาพมากกว่าการค้นหาหรือสแกนข้อมูล

ขั้นตอนถัดไป