PEMBARUAN : Sekarang ada dokumen tentang penataan data . Juga, lihat posting luar biasa ini tentang struktur data NoSQL .
Masalah utama dengan data hierarkis, sebagai lawan dari RDBMS, adalah menggoda data bersarang karena kami bisa. Umumnya, Anda ingin menormalkan data sampai batas tertentu (seperti yang akan Anda lakukan dengan SQL) meskipun tidak ada pernyataan dan kueri gabungan.
Anda juga ingin melakukan denormalisasi di tempat-tempat yang mengutamakan efisiensi membaca. Ini adalah teknik yang digunakan oleh semua aplikasi berskala besar (misalnya Twitter dan Facebook) dan meskipun bertentangan dengan prinsip KERING kami, teknik ini umumnya merupakan fitur yang diperlukan dari aplikasi yang dapat diskalakan.
Intinya di sini adalah Anda ingin bekerja keras dalam menulis untuk memudahkan pembacaan. Jaga agar komponen logis yang dibaca terpisah terpisah (misalnya untuk ruang obrolan, jangan letakkan pesan, info meta tentang ruang, dan daftar anggota semua di tempat yang sama, jika Anda ingin dapat mengulang grup nanti).
Perbedaan utama antara data real-time Firebase dan lingkungan SQL adalah membuat kueri data. Tidak ada cara sederhana untuk mengatakan "PILIH PENGGUNA DI MANA X = Y", karena sifat data waktu nyata (terus berubah, memisahkan, merekonsiliasi, dll., Yang membutuhkan model internal yang lebih sederhana untuk menjaga klien yang disinkronkan tetap terkendali)
Contoh sederhana mungkin akan membuat Anda berada dalam kondisi pikiran yang benar, jadi begini:
/users/uid
/users/uid/email
/users/uid/messages
/users/uid/widgets
Sekarang, karena kita berada dalam struktur hierarki, jika saya ingin mengulang alamat email pengguna, saya melakukan sesuatu seperti ini:
// I could also use on('child_added') here to great success
// but this is simpler for an example
firebaseRef.child('users').once('value')
.then(userPathSnapshot => {
userPathSnapshot.forEach(
userSnap => console.log('email', userSnap.val().email)
);
})
.catch(e => console.error(e));
Masalah dengan pendekatan ini adalah saya baru saja memaksa klien untuk mengunduh semua pengguna messages
dan widgets
juga. Bukan masalah besar jika tidak ada yang jumlahnya ribuan. Tetapi masalah besar untuk 10k pengguna dengan masing-masing lebih dari 5k pesan.
Jadi sekarang strategi optimal untuk hierarki, struktur waktu nyata menjadi lebih jelas:
/user_meta/uid/email
/messages/uid/...
/widgets/uid/...
Alat tambahan yang sangat berguna dalam lingkungan ini adalah indeks. Dengan membuat indeks pengguna dengan atribut tertentu, saya dapat dengan cepat mensimulasikan kueri SQL hanya dengan mengulang indeks:
/users_with_gmail_accounts/uid/email
Sekarang jika saya ingin, katakanlah, mendapatkan pesan untuk pengguna gmail, saya bisa melakukan sesuatu seperti ini:
var ref = firebase.database().ref('users_with_gmail_accounts');
ref.once('value').then(idx_snap => {
idx_snap.forEach(idx_entry => {
let msg = idx_entry.name() + ' has a new message!';
firebase.database().ref('messages').child(idx_entry.name())
.on(
'child_added',
ss => console.log(msg, ss.key);
);
});
})
.catch(e => console.error(e));
Saya menawarkan beberapa detail di posting SO lain tentang denormalisasi data, jadi periksa juga . Saya melihat bahwa Frank sudah memposting artikel Anant, jadi saya tidak akan mengulanginya di sini, tapi ini juga bacaan yang bagus.