Ikuti semua informasi yang diumumkan di Firebase Summit, dan pelajari bagaimana Firebase dapat membantu Anda mempercepat pengembangan aplikasi dan menjalankan aplikasi dengan percaya diri. Pelajari Lebih Lanjut

Struktur Basis Data Anda

Panduan ini mencakup beberapa konsep utama dalam arsitektur data dan praktik terbaik untuk menyusun data JSON di Firebase Realtime Database Anda.

Membangun database yang terstruktur dengan baik membutuhkan sedikit pemikiran ke depan. Yang terpenting, Anda perlu merencanakan bagaimana data akan disimpan dan kemudian diambil kembali untuk membuat proses itu semudah mungkin.

Bagaimana struktur data: ini adalah pohon JSON

Semua data Firebase Realtime Database disimpan sebagai objek JSON. Anda dapat menganggap database sebagai pohon JSON yang dihosting di cloud. Tidak seperti database SQL, tidak ada tabel atau record. Saat Anda menambahkan data ke pohon JSON, data tersebut menjadi simpul dalam struktur JSON yang ada dengan kunci terkait. Anda dapat memberikan kunci Anda sendiri, seperti ID pengguna atau nama semantik, atau dapat diberikan untuk Anda menggunakan childByAutoId .

Jika Anda membuat kunci sendiri, kunci tersebut harus berenkode UTF-8, maksimal 768 byte, dan tidak boleh berisi . , $ , # , [ , ] , / , atau karakter kontrol ASCII 0-31 atau 127. Anda juga tidak dapat menggunakan karakter kontrol ASCII dalam nilai itu sendiri.

Misalnya, pertimbangkan aplikasi obrolan yang memungkinkan pengguna menyimpan profil dasar dan daftar kontak. Profil pengguna tipikal terletak di jalur, seperti /users/$uid . Pengguna alovelace mungkin memiliki entri basis data yang terlihat seperti ini:

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

Meskipun database menggunakan pohon JSON, data yang disimpan dalam database dapat direpresentasikan sebagai tipe asli tertentu yang sesuai dengan tipe JSON yang tersedia untuk membantu Anda menulis kode yang lebih dapat dikelola.

Praktik terbaik untuk struktur data

Hindari data bersarang

Karena Firebase Realtime Database memungkinkan pengumpulan data hingga kedalaman 32 level, Anda mungkin tergoda untuk berpikir bahwa ini harus menjadi struktur default. Namun, saat Anda mengambil data di suatu lokasi di database, Anda juga mengambil semua simpul turunannya. Selain itu, saat Anda memberi seseorang akses baca atau tulis di sebuah node di database Anda, Anda juga memberi mereka akses ke semua data di bawah node tersebut. Oleh karena itu, dalam praktiknya, sebaiknya jaga agar struktur data Anda tetap datar.

Sebagai contoh mengapa data bersarang buruk, pertimbangkan struktur bersarang ganda berikut:

{
  // 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": { ... }
  }
}

Dengan desain bersarang ini, iterasi melalui data menjadi bermasalah. Misalnya, daftar judul percakapan obrolan memerlukan keseluruhan pohon chats , termasuk semua anggota dan pesan, untuk diunduh ke klien.

Meratakan struktur data

Jika data malah dipecah menjadi jalur terpisah, juga disebut denormalisasi, itu dapat diunduh secara efisien dalam panggilan terpisah, sesuai kebutuhan. Pertimbangkan struktur yang rata ini:

{
  // 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": { ... }
  }
}

Iterasi melalui daftar ruangan kini dapat dilakukan dengan hanya mengunduh beberapa byte per percakapan, dengan cepat mengambil metadata untuk mencantumkan atau menampilkan ruangan di UI. Pesan dapat diambil secara terpisah dan ditampilkan saat tiba, memungkinkan UI tetap responsif dan cepat.

Buat data yang berskala

Saat membuat aplikasi, sering kali lebih baik mengunduh subset dari daftar. Ini sangat umum jika daftar berisi ribuan catatan. Saat hubungan ini statis dan satu arah, Anda cukup menumpuk objek anak di bawah objek induk.

Terkadang, hubungan ini lebih dinamis, atau mungkin perlu dilakukan denormalisasi data ini. Sering kali Anda dapat melakukan denormalisasi data dengan menggunakan kueri untuk mengambil subkumpulan data, seperti yang dibahas dalam Mengambil Data .

Tetapi bahkan ini mungkin tidak cukup. Pertimbangkan, misalnya, hubungan dua arah antara pengguna dan grup. Pengguna dapat menjadi bagian dari grup, dan grup terdiri dari daftar pengguna. Ketika tiba waktunya untuk memutuskan grup mana yang dimiliki pengguna, segalanya menjadi rumit.

Yang diperlukan adalah cara yang elegan untuk membuat daftar grup tempat pengguna berada dan hanya mengambil data untuk grup tersebut. Indeks grup dapat sangat membantu di sini:

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

Anda mungkin memperhatikan bahwa ini menggandakan beberapa data dengan menyimpan hubungan di bawah catatan Ada dan di bawah grup. Sekarang alovelace diindeks di bawah grup, dan techpioneers terdaftar di profil Ada. Jadi untuk menghapus Ada dari grup, itu harus diperbarui di dua tempat.

Ini adalah redundansi yang diperlukan untuk hubungan dua arah. Ini memungkinkan Anda mengambil keanggotaan Ada dengan cepat dan efisien, bahkan ketika daftar pengguna atau grup mencapai jutaan atau ketika aturan keamanan Realtime Database mencegah akses ke beberapa catatan.

Pendekatan ini, membalikkan data dengan mencantumkan ID sebagai kunci dan menyetel nilainya ke true, membuat pemeriksaan kunci semudah membaca /users/$uid/groups/$group_id dan memeriksa apakah itu null . Indeks lebih cepat dan jauh lebih efisien daripada menanyakan atau memindai data.

Langkah selanjutnya