33 votes

Relation many to many dans Firebase

J'ai une base de données Firebase. J'ai des Entreprises et des Entrepreneurs. Un Entrepreneur peut travailler pour plus d'une Entreprise et une Entreprise peut avoir plusieurs Entrepreneurs. Il s'agit d'une relation de plusieurs à plusieurs. Je veux pouvoir répondre aux questions sur les Entreprises et les Entrepreneurs :

  1. Étant donné une Entreprise, qui sont les Entrepreneurs actuels.
  2. Étant donné un Entrepreneur, pour quelles Entreprises travaillent-ils.

Quelles sont les alternatives pour structurer les données dans Firebase?

28voto

Frank van Puffelen Points 16029

L'auto-réponse est en effet une façon de modéliser ceci. C'est probablement l'équivalent le plus direct de la façon dont vous modéliseriez ceci dans une base de données relationnelle :

  • contractors
  • companies
  • companyAndContractorsAssignment (la table de connexion many-to-many)

Une alternative serait d'utiliser 4 nœuds de premier niveau :

  • contractors
  • companies
  • companyContractors
  • contractorCompanies

Les deux derniers nœuds ressembleraient à :

companyContractors
    companyKey1
        contractorKey1: true
        contractorKey3: true
    companyKey2
        contractorKey2: true
contractorCompanies
    contractorKey1
        companyKey1: true
    contractorKey2
        companyKey2: true
    contractorKey3
        companyKey1: true

Cette structure bidirectionnelle vous permet de rechercher à la fois les "contractors pour une entreprise" et les "entreprises pour un contractor", sans que l'un de ces besoins soit une requête. Cela est censé être plus rapide, surtout lorsque vous ajoutez des contractors et des entreprises.

Que cela soit nécessaire pour votre application dépend des cas d'utilisation dont vous avez besoin, des tailles de données que vous attendez et bien plus encore.

Lecture recommandée la modélisation des données NoSQL et visualisation Firebase pour les développeurs SQL. Cette question a également été présentée dans un épisode de la série youtube #AskFirebase.

Mise à jour (2017016)

Quelqu'un a publié une question de suivi qui est liée ici concernant la récupération des articles réels des nœuds "contractors" et "companies". Vous devrez les récupérer un par un, car Firebase n'a pas l'équivalent de SELECT * FROM table WHERE id IN (1,2,3). Mais cette opération n'est pas aussi lente que vous pourriez le penser, car les requêtes sont mises en pipeline sur une seule connexion. En savoir plus à ce sujet ici : Accélérer le chargement des publications de mon application de réseau social en utilisant une requête au lieu d'observer un événement unique à plusieurs reprises.

6voto

Rob Gorman Points 1456

Après plus de recherches, je vais essayer de répondre à ma propre question. J'ai examiné un certain nombre d'autres publications et une solution au problème de many-to-many est de stocker une liste de ContractorKeys dans un objet Company et de stocker une liste de CompanyKeys dans chaque objet contractant. Cela est illustré avec un exemple ci-dessous.

companies : {
  companyKey1 : {
    name : company1
    ...
    contractors : {
      contractorKey1 : true,   
      contractorKey3 : true
    }
  }
  companyKey2 : {
    name : company2
    ...
    contractors : {
      contractorKey2 : true,  
    } 
  }
}
contrators : {
  contractorKey1 : {
     name : bill
     ...
     companies : {
        companyKey1 : true
     }
   }
  contractorKey2 : {
     name : steve
     ...
     companies : {
        companyKey1 : true
     }

   }
  contractorKey3 : {
     name : jim
     ...
     companies : {
        companyKey2 : true
     }
   }
}

Cette organisation "fonctionne" dans le sens où les questions mentionnées précédemment peuvent être répondues. Mais un inconvénient de cette solution est qu'il y a deux listes à maintenir lorsque les affectations Contractor/Company changent. Il serait mieux s'il y avait un moyen de représenter ces informations dans une seule liste.

Je pense avoir trouvé une meilleure solution. La solution est de créer une troisième liste, en plus de companies et contractors appelée companyAndContractorAssignment. Les éléments de cette liste représenteront une relation entre un seul contractant et une entreprise. Son contenu sera une paire de champs, le contractorKey et le companyKey. Nous pouvons ensuite éliminer la liste des entrepreneurs au sein de l'entreprise et la liste des entreprises chez le contractant. Cette structure alternative est représentée ci-dessous. Remarquez qu'il n'y a pas de liste d'entrepreneurs dans un objet d'entreprise et pas de liste d'entreprises dans un objet de contractant.

companies : {
  companyKey1 : {
    name : company1
    ...
  }
  companyKey2 : {
    name : company2
    ...
  }
}
contrators : {
  contractorKey1 : {
     name : bill
     ...
  }
  contractorKey2 : {
     name : steve
     ...
  }
  contractorKey3 : {
     name : jim
     ...
  }
}
companyAndContractorsAssignment : {
  key1 : {
    contractorKey1 : true,
    companyKey1: true,
  }
  key2 : {
    contractorKey3 : true,
    companyKey1: true,
  }
  key3 : {
    contractorKey2 : true,
    companyKey2: true,
  }

Cette structure alternative permet de répondre aux questions en utilisant une requête orderByChild/equalTo sur companyAndContractorsAssignment pour trouver toutes les entreprises pour un contractant ou tous les contractants pour une entreprise. Et il n'y a maintenant qu'une seule liste à maintenir. Je pense que c'est la meilleure solution pour mes besoins.

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