120 votes

Quelle est la meilleure façon de structurer les données sur firebase ?

Je suis nouveau sur firebase et je veux savoir quelle est la meilleure façon de structurer les données sur firebase.

J'ai un exemple simple :

Il y a des candidats et des demandes sur mon projet. Un candidat peut avoir plusieurs applications. Comment puis-je relier ces deux objets sur Firebase ? Cela fonctionne-t-il comme une base de données relationnelle ? Ou l'approche doit-elle être complètement différente en termes de conception des données ?

152voto

Kato Points 12210

UPDATE : Il y a maintenant un doc sur la structuration des données . Voir également cet excellent article sur Structures de données NoSQL .

Le principal problème des données hiérarchiques, par opposition aux SGBDR, est qu'il est tentant d'imbriquer les données parce qu'on le peut. En général, vous souhaitez normaliser les données dans une certaine mesure (tout comme vous le feriez avec SQL) malgré l'absence d'instructions de jointure et de requêtes.

Vous souhaitez également dénormaliser dans les endroits où l'efficacité de la lecture est une préoccupation. C'est une technique utilisée par toutes les applications à grande échelle (par exemple Twitter et Facebook) et bien qu'elle aille à l'encontre de nos principes DRY, c'est généralement une caractéristique nécessaire des applications évolutives.

L'essentiel ici est que vous devez travailler dur sur les écritures pour rendre les lectures faciles. Gardez les composants logiques qui sont lus séparément (par exemple, pour les salons de discussion, ne mettez pas les messages, les méta-informations sur les salons et les listes de membres au même endroit, si vous voulez pouvoir itérer les groupes plus tard).

La principale différence entre les données en temps réel de Firebase et un environnement SQL est l'interrogation des données. Il n'y a pas de moyen simple de dire "SELECT USERS WHERE X = Y", en raison de la nature en temps réel des données (elles sont constamment modifiées, partagées, réconciliées, etc., ce qui nécessite un modèle interne plus simple pour contrôler les clients synchronisés).

Un simple exemple vous mettra probablement dans le bon état d'esprit, alors voilà :

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

Maintenant, puisque nous sommes dans une structure hiérarchique, si je veux itérer les adresses électroniques des utilisateurs, je fais quelque chose comme ceci :

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

Le problème avec cette approche est que je viens de forcer le client à télécharger toutes les données des utilisateurs. messages y widgets aussi. Ce n'est pas grave si aucune de ces choses ne se compte en milliers. Mais un gros problème pour 10 000 utilisateurs avec plus de 5 000 messages chacun.

La stratégie optimale pour une structure hiérarchique en temps réel devient donc plus évidente :

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

Les index sont un outil supplémentaire extrêmement utile dans cet environnement. En créant un index des utilisateurs avec certains attributs, je peux rapidement simuler une requête SQL en itérant simplement l'index :

/users_with_gmail_accounts/uid/email

Maintenant, si je veux, disons, obtenir les messages des utilisateurs de gmail, je peux faire quelque chose comme ceci :

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

J'ai donné quelques détails dans un autre billet de SO sur la dénormalisation des données, alors vérifiez-les aussi . Je vois que Frank a déjà publié l'article d'Anant, je ne vais donc pas le répéter ici, mais c'est aussi une excellente lecture.

50voto

Frank van Puffelen Points 16029

Firebase est très pas comme une base de données relationnelle. Si vous voulez la comparer à quelque chose, je la comparerais à une base de données hiérarchique.

Anant a récemment écrit un excellent article sur le blog de Firebase sur la dénormalisation de vos données : https://www.firebase.com/blog/2013-04-12-denormalizing-is-normal.html

Je suggère en effet de conserver l'"ID" de chaque demande comme enfant de chaque demandeur.

4voto

Prateep Gedupudi Points 121

Votre scénario ressemble à un "one to many" dans le monde relationnel, comme dans votre exemple, un candidat a plusieurs demandes. Si nous en venons à la méthode firebase nosql, cela ressemble à ce qui suit. Il devrait évoluer sans aucun problème de performance. C'est pourquoi nous avons besoin de dénormalisation comme mentionné ci-dessous.

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

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X