GÜNCELLEME : Artık verilerin yapılandırılmasına ilişkin bir belge var . Ayrıca, NoSQL veri yapıları hakkındaki bu mükemmel gönderiye bakın .
RDBMS'nin aksine hiyerarşik verilerle ilgili ana sorun, yapabildiğimiz için verileri iç içe yerleştirmenin cazip olmasıdır. Genel olarak, birleştirme ifadeleri ve sorguları olmamasına rağmen verileri bir dereceye kadar normalleştirmek istersiniz (tıpkı SQL'de yaptığınız gibi).
Ayrıca , okuma verimliliğinin önemli olduğu yerlerde normalden uzaklaşmak istersiniz . Bu, tüm büyük ölçekli uygulamalarda (ör. Twitter ve Facebook) kullanılan bir tekniktir ve DRY ilkelerimize aykırı olmasına rağmen, genellikle ölçeklenebilir uygulamaların gerekli bir özelliğidir.
Buradaki esas, okumaları kolaylaştırmak için yazılar üzerinde çok çalışmak istemenizdir. Ayrı ayrı okunan mantıksal bileşenleri ayrı tutun (örneğin, grupları daha sonra yineleyebilmek istiyorsanız, sohbet odaları için mesajları, odalar hakkındaki meta bilgileri ve üye listelerini aynı yere koymayın).
Firebase'in gerçek zamanlı verileri ile bir SQL ortamı arasındaki temel fark, verileri sorgulamaktır. Verinin gerçek zamanlı doğası nedeniyle "X = Y OLDUĞUNDA KULLANICILARI SEÇİN" demenin basit bir yolu yoktur (sürekli olarak değişir, parçalanır, uzlaştırılır, bu da senkronize edilmiş istemcileri kontrol altında tutmak için daha basit bir dahili model gerektirir)
Basit bir örnek muhtemelen sizi doğru zihin durumuna getirecektir, işte burada:
/users/uid
/users/uid/email
/users/uid/messages
/users/uid/widgets
Şimdi, hiyerarşik bir yapıda olduğumuz için, kullanıcıların e-posta adreslerini yinelemek istersem, şöyle bir şey yapıyorum:
// 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));
Bu yaklaşımdaki sorun sadece kullanıcılara tümünü indirmeyi müşteri zorladı olmasıdır messages
ve widgets
çok. Bunların hiçbiri binlerce değilse bile önemli değil. Ancak, her biri 5.000'den fazla mesaj içeren 10.000 kullanıcı için büyük bir sorun.
Şimdi hiyerarşik, gerçek zamanlı bir yapı için en uygun strateji daha açık hale geliyor:
/user_meta/uid/email
/messages/uid/...
/widgets/uid/...
Bu ortamda son derece yararlı olan ek bir araç endekslerdir. Belirli özniteliklere sahip bir kullanıcı dizini oluşturarak, dizini yineleyerek bir SQL sorgusunu hızlı bir şekilde simüle edebilirim:
/users_with_gmail_accounts/uid/email
Şimdi, diyelim ki gmail kullanıcıları için mesajlar almak istersem, bunun gibi bir şey yapabilirim:
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));
Başka bir SO gönderisinde verileri denormalize etme hakkında bazı ayrıntılar sundum, bu yüzden bunları da kontrol edin . Frank'in Anant'ın makalesini zaten yayınladığını görüyorum, bu yüzden burada tekrar etmeyeceğim, ama aynı zamanda harika bir okuma.