2013-05-07 18 views
91

Sono nuovo di Firebase e voglio sapere qual è il modo migliore di strutturare i dati su di esso.Qual è il modo migliore per strutturare i dati su Firebase?

Ho un semplice esempio:

ci sono candidati e applicazioni sul mio progetto. 1 richiedente può avere diverse applicazioni. Come posso mettere in relazione questi 2 oggetti con Firebase? Funziona come un database relazionale? O l'approccio deve essere completamente diverso in termini di progettazione dei dati?

risposta

119

UPDATE: Ora c'è un doc on structuring data. Inoltre, guarda questo post eccellente su NoSQL data structures.

Il problema principale con i dati gerarchici, a differenza di RDBMS, è che si è tentati di annidare i dati perché possiamo. In generale, si desidera normalizzare i dati in una certa misura (proprio come si farebbe con SQL) nonostante la mancanza di istruzioni e query di join.

Si desidera anche denormalize in luoghi in cui l'efficienza di lettura è un problema. Questa è una tecnica utilizzata da tutte le app su larga scala (ad esempio Twitter e Facebook) e, sebbene vada contro i nostri principi DRY, è generalmente una caratteristica necessaria delle app scalabili.

L'essenza qui è che si vuole lavorare sodo su scritture per semplificare la lettura. Mantieni separati i componenti logici che vengono letti separatamente (ad es. Per le chat room, non mettere i messaggi, le meta informazioni sulle stanze e gli elenchi dei membri tutti nello stesso posto, se vuoi essere in grado di iterare i gruppi in seguito).

La differenza principale tra i dati in tempo reale di Firebase e un ambiente SQL è la query dei dati. Non esiste un modo semplice per dire "SELEZIONA GLI UTENTI DOVE X = Y", a causa della natura in tempo reale dei dati (è in continua evoluzione, sharding, riconciliazione, ecc., Che richiede un modello interno più semplice per tenere sotto controllo i client sincronizzati)

un semplice esempio sarà probabilmente si imposta nel giusto stato d'animo, quindi ecco qui:

/users/uid 
/users/uid/email 
/users/uid/messages 
/users/uid/widgets 

Ora, dal momento che siamo in una struttura gerarchica, se voglio iterare indirizzi di posta elettronica degli utenti, Faccio qualcosa del genere:

// 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)); 

Il problema con questo approccio è che ho appena costretto il client a scaricare tutti gli utenti messages e widgets. Nessun problema se nessuna di queste cose è in migliaia. Ma un grosso problema per 10k utenti con un massimo di 5k messaggi ciascuno.

Così ora la strategia ottimale per un gerarchica, struttura in tempo reale diventa più evidente:

/user_meta/uid/email 
/messages/uid/... 
/widgets/uid/... 

Un ulteriore strumento che è estremamente utile in questo contesto sono indici.Con la creazione di un indice di utenti con determinati attributi, posso simulare rapidamente una query SQL, semplicemente scorrendo l'indice:

/users_with_gmail_accounts/uid/email 

Ora, se voglio, per esempio, avere messaggi per gli utenti di Gmail, posso fare qualcosa di simile :

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)); 

ho offerto alcuni dettagli in un altro SO post su dati denormalizing, so check those out as well. Vedo che Frank ha già pubblicato l'articolo di Anant, quindi non lo ripeterò qui, ma è anche una buona lettura.

+0

Grazie per questa intuizione Kato! –

+4

Devo gestire questi indici manualmente? – fiatjaf

+2

Per ora. Le visualizzazioni nella versione v2 di Firebase conterranno alcune grandi capacità per l'automazione di quel processo. – Kato

44

Firebase è molto non come un database relazionale. Se vuoi confrontarlo con qualcosa, lo paragonerei a un database gerarchico.

Anant ha recentemente scritto un grande post sopra sul blog Firebase su denormalizing i tuoi dati: https://www.firebase.com/blog/2013-04-12-denormalizing-is-normal.html

mi piacerebbe davvero suggerire mantenendo la "ID" di ogni applicazione come un bambino di ciascun richiedente.

+0

Yuppers! Ottimo post! Grazie per avermelo ricordato. – Kato

+0

Grazie Frank! Questo è veramente utile. Esattamente quello che stavo cercando! –

3

Il tuo scenario appare come uno a molti nel mondo relazionale, come nel tuo esempio un candidato ha molte applicazioni. Se arriviamo alla base di Firebase nosql, sembra che qui di seguito. Dovrebbe scalare senza problemi di prestazioni. Ecco perché abbiamo bisogno di denormalizzazione come indicato di seguito.

applicants:{ 
applicant1:{ 
    . 
    . 
    applications:{ 
     application1:true, 
     application3:true 
    } 
}, 
applicant2:{ 
    . 
    . 
    applications:{ 
     application2:true, 
     application4:true 
    } 
}} 

applications:{ 
application1:{ 
    . 
    . 
}, 
application2:{ 
    . 
    . 
}, 
application3:{ 
    . 
    . 
}, 
application4:{ 
    . 
    . 
}} 
+0

Buono ma ho un seguito, come possiamo creare questa struttura da Swift o da qualsiasi luogo utilizzando l'SDK Firebase? Inoltre, come possiamo verificare che i nuovi dati aggiunti al nodo delle applicazioni siano effettivamente presenti nell'elenco delle applicazioni che utilizza le regole di convalida di Firebase? –

+0

@prateep, buon esempio. Ma qui problema è quando elimino applicazioni di percorso/application1 dove application1 è child per alcuni candidati. Se provo ad accedere ai candidati di percorso/applicazione1 che non è lì. quindi è necessario aggiornare gli indici in entrambi i posti come application1: {candidati: {candidato1: vero} ...} così ora quando elimino l'applicazione1 devo controllare i suoi candidati secondari e aggiornare il nodo figlio dell'applicativo per l'applicazione. :) –

Problemi correlati