web-dev-qa-db-fra.com

Relation plusieurs à plusieurs dans Firebase

J'ai une base de données Firebase. J'ai des entreprises et des entrepreneurs. Un entrepreneur peut travailler pour plusieurs entreprises et une entreprise peut avoir plusieurs entrepreneurs. Il s'agit d'une relation simple 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?

33
Rob Gorman

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

  • entrepreneurs
  • entreprises
  • companyAndContractorsAssignment (la table de connecteurs plusieurs à plusieurs)

Une alternative serait d'utiliser 4 nœuds de niveau supérieur:

  • entrepreneurs
  • entreprises
  • entrepriseContractants
  • entrepreneurEntreprises

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 à la fois de rechercher des "sous-traitants pour une entreprise" et des "sociétés pour un sous-traitant", sans que l'une ou l'autre d'entre elles ne soit une requête. Cela devrait être plus rapide, surtout lorsque vous ajoutez des entrepreneurs et des entreprises.

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

Lecture recommandée 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 renvoie ici sur la récupération des éléments réels des nœuds "sous-traitants" et "entreprises". Vous devrez les récupérer un par un, car Firebase n'a pas d'équivalent à SELECT * FROM table WHERE id IN (1,2,3). Mais cette opération n'est pas aussi lente que vous le pensez, car les demandes sont acheminées via une seule connexion. En savoir plus à ce sujet ici: Accélérez la récupération des messages pour mon application de réseau social en utilisant une requête au lieu d'observer un seul événement à plusieurs reprises .

25
Frank van Puffelen

Après de plus amples recherches, je vais essayer de répondre à ma propre question. J'ai examiné un certain nombre d'autres articles et une solution au problème plusieurs-à-plusieurs consiste à stocker une liste de ContractorKeys dans un objet Company et à stocker une liste de CompanyKeys dans chaque objet Contractor. Ceci est illustré par 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" en ce sens qu'il est possible de répondre aux questions susmentionnées. Mais un inconvénient de cette solution est qu'il y a deux listes à maintenir lorsque les affectations de l'entrepreneur/de l'entreprise changent. Il serait préférable qu'il y ait un moyen de représenter ces informations dans une seule liste.

Je pense avoir trouvé une meilleure solution. La solution consiste à créer une troisième liste, en plus des entreprises et des entrepreneurs appelés companyAndContractorAssignment. Les éléments de cette liste représenteront une relation entre un seul entrepreneur et une entreprise. Son contenu sera une paire de champs, la clé de l'entrepreneur et la clé de l'entreprise. Nous pouvons alors éliminer la liste des entrepreneurs au sein de l'entreprise et la liste des entreprises au sein de l'entrepreneur. Cette structure alternative est représentée ci-dessous. Notez qu'il n'y a pas de liste d'entrepreneurs dans un objet d'entreprise et aucune liste d'entreprises avec un objet d'entrepreneur.

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 entrepreneur ou tous les entrepreneurs pour une entreprise. Et il n'y a plus qu'une seule liste à maintenir. Je pense que c'est la meilleure solution pour mes besoins.

5
Rob Gorman