web-dev-qa-db-fra.com

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

Je suis nouveau sur firebase et je veux savoir quel est le meilleur moyen de structurer les données à ce sujet.

J'ai un exemple simple:

Il y a des candidats et des applications sur mon projet. 1 demandeur peut avoir plusieurs applications. Comment puis-je relier ces 2 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 de données?

107
Ricardo Parro

[~ # ~] update [~ # ~] : Il existe maintenant un doc sur la structuration des données . Voir aussi cet excellent article sur structures de données NoSQL .

Le problème principal des données hiérarchiques, par opposition au SGBDR, est qu'il est tentant d'imbriquer des données parce que nous le pouvons. En règle générale, vous souhaitez normaliser les données dans une certaine mesure (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 un problème. Il s’agit d’une technique utilisée par toutes les applications à grande échelle (par exemple Twitter et Facebook) et bien qu’elle soit contraire à nos principes DRY), c’est généralement une fonctionnalité indispensable des applications évolutives.

En résumé, vous voulez travailler dur pour faciliter la lecture. Conservez les composants logiques lus séparément (par exemple, pour les salles de discussion, ne mettez pas les messages, les méta-informations relatives aux salles et les listes de membres au même endroit, si vous souhaitez pouvoir réitérer les groupes ultérieurement).

La principale différence entre les données en temps réel de Firebase et un environnement SQL réside dans l'interrogation des données. Il n'y a pas de moyen simple de dire "CHOISISSEZ LES UTILISATEURS OU X = Y", en raison de la nature en temps réel des données (elles changent constamment, se partagent, se réconcilient, etc., ce qui nécessite un modèle interne plus simple pour contrôler les clients synchronisés).

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

/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 d’obliger le client à télécharger tous les utilisateurs messages et widgets. 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.

Alors maintenant, la stratégie optimale pour une structure hiérarchique en temps réel devient 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 d'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, par exemple, obtenir des messages pour les 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 présenté quelques détails dans un autre SO article sur la dénormalisation des données, vérifiez-les également . Je vois que Frank a déjà publié l'article d'Anant, je ne vais donc pas répéter. ici, mais c’est aussi une excellente lecture.

135
Kato

Firebase ressemble beaucoup à à une base de données relationnelle. Si vous voulez le comparer à quelque chose, je le comparerais à une base de données hiérarchique.

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

Je suggèrerais en effet de conserver la "pièce d'identité" de chaque demande en tant qu'enfant de chaque demandeur.

48

Votre scénario ressemble à un sur plusieurs dans le monde relationnel, selon votre exemple, un demandeur a de nombreuses applications. Si nous en arrivons à la base de nosql, elle ressemble à celle ci-dessous. 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:{
    .
    .
}}
4
Prateep Gedupudi