Comment feriez-vous une association plusieurs-à-plusieurs avec MongoDB?
Par exemple; disons que vous avez une table Users et une table Roles. Les utilisateurs ont de nombreux rôles et les rôles ont de nombreux utilisateurs. Dans SQL land, vous créeriez une table UserRoles.
Users:
Id
Name
Roles:
Id
Name
UserRoles:
UserId
RoleId
Comment le même type de relation est-il géré dans MongoDB?
many-to-many
associations
mongodb
Josh Fermer
la source
la source
Réponses:
En fonction de vos besoins de requête, vous pouvez tout mettre dans le document utilisateur:
Pour obtenir tous les ingénieurs, utilisez:
Si vous souhaitez conserver les rôles dans des documents séparés, vous pouvez inclure le _id du document dans le tableau des rôles au lieu du nom:
et configurez les rôles comme:
la source
Au lieu d'essayer de modéliser en fonction de nos années d'expérience avec les SGBDR, j'ai trouvé beaucoup plus facile de modéliser des solutions de référentiel de documents à l'aide de MongoDB, Redis et d'autres magasins de données NoSQL en optimisant pour les cas d'utilisation de lecture, tout en tenant compte de l'atome les opérations d'écriture qui doivent être prises en charge par les cas d'utilisation d'écriture.
Par exemple, les utilisations d'un domaine «Utilisateurs dans des rôles» sont les suivantes:
Cela peut être modélisé comme les modèles de document suivants:
Pour prendre en charge les utilisations à haute fréquence, telles que les fonctionnalités liées au rôle de l'entité utilisateur, User.Roles est intentionnellement dénormalisé, stocké sur l'utilisateur ainsi que sur Role.Users ayant un stockage en double.
Si ce n'est pas évident dans le texte, mais c'est le type de réflexion qui est encouragé lors de l'utilisation de référentiels de documents.
J'espère que cela aidera à combler le fossé en ce qui concerne le côté lecture des opérations.
Pour le côté écriture, ce qui est encouragé est de modéliser selon les écritures atomiques. Par exemple, si les structures de document nécessitent l'acquisition d'un verrou, la mise à jour d'un document, puis un autre et éventuellement plus de documents, puis la libération du verrou, il est probable que le modèle a échoué. Ce n'est pas parce que nous pouvons créer des verrous distribués que nous sommes censés les utiliser.
Dans le cas du modèle User in Roles, les opérations qui étendent notre évitement des verrous en écriture atomique consistent à ajouter ou à supprimer un utilisateur d'un rôle. Dans les deux cas, une opération réussie entraîne la mise à jour d'un seul utilisateur et d'un seul document de rôle. Si quelque chose échoue, il est facile d'effectuer un nettoyage. C'est la seule raison pour laquelle le modèle d'unité de travail est souvent utilisé lorsque les référentiels de documents sont utilisés.
L'opération qui étend vraiment notre évitement des verrous en écriture atomique consiste à effacer un rôle, ce qui entraînerait de nombreuses mises à jour d'utilisateur pour supprimer le Role.name du tableau User.roles. Cette opération d'effacement est alors généralement déconseillée, mais si nécessaire peut être mise en œuvre en ordonnant les opérations:
Dans le cas d'un problème, qui est le plus susceptible de se produire à l'étape 2, une restauration est facile car le même ensemble de noms d'utilisateur de l'étape 1 peut être utilisé pour récupérer ou continuer.
la source
Je viens de tomber sur cette question et, bien qu'elle soit ancienne, j'ai pensé qu'il serait utile d'ajouter quelques possibilités non mentionnées dans les réponses données. De plus, les choses ont un peu évolué ces dernières années, il convient donc de souligner que SQL et NoSQL se rapprochent l'un de l'autre.
Un des commentateurs a évoqué la sage attitude de prudence selon laquelle «si les données sont relationnelles, utilisez relationnelles». Cependant, ce commentaire n'a de sens que dans le monde relationnel, où les schémas viennent toujours avant l'application.
MONDE RELATIONNEL: Structurer les données> Ecrire une application pour l'obtenir
NOSQL WORLD: Concevoir une application> Structurer les données en conséquence
Même si les données sont relationnelles, NoSQL reste une option. Par exemple, les relations un-à-plusieurs ne posent aucun problème et sont largement couvertes dans la documentation MongoDB
UNE SOLUTION 2015 À UN PROBLÈME DE 2010
Depuis que cette question a été publiée, il y a eu de sérieuses tentatives pour rapprocher noSQL de SQL. L'équipe dirigée par Yannis Papakonstantinou à l'Université de Californie (San Diego) a travaillé sur FORWARD , une implémentation de SQL ++ qui pourrait bientôt être la solution à des problèmes persistants comme celui posté ici.
À un niveau plus pratique, la sortie de Couchbase 4.0 a signifié que, pour la première fois, vous pouvez faire des JOIN natifs dans NoSQL. Ils utilisent leur propre N1QL. Voici un exemple d'un
JOIN
de leurs tutoriels :N1QL permet la plupart sinon toutes les opérations SQL, y compris l'agrégation, le filtrage, etc.
LA SOLUTION HYBRIDE PAS SI NOUVELLE
Si MongoDB est toujours la seule option, alors j'aimerais revenir sur mon point selon lequel l'application doit avoir priorité sur la structure des données. Aucune des réponses ne mentionne l'incorporation hybride, dans laquelle la plupart des données interrogées sont incorporées dans le document / objet et les références sont conservées pour une minorité de cas.
Exemple: des informations (autres que le nom du rôle) peuvent-elles attendre? Le démarrage de l'application pourrait-il être plus rapide en ne demandant rien dont l'utilisateur n'a pas encore besoin?
Cela pourrait être le cas si l'utilisateur se connecte et qu'il / elle a besoin de voir toutes les options pour tous les rôles auxquels il appartient. Cependant, l'utilisateur est un «ingénieur» et les options pour ce rôle sont rarement utilisées. Cela signifie que l'application n'a besoin que d'afficher les options pour un ingénieur au cas où il / elle voudrait cliquer dessus.
Ceci peut être réalisé avec un document qui indique à l'application au début (1) à quels rôles l'utilisateur appartient et (2) où obtenir des informations sur un événement lié à un rôle particulier.
Ou, mieux encore, indexez le champ role.name dans la collection de rôles, et vous n'aurez peut-être pas besoin d'incorporer ObjectID () non plus.
Autre exemple: des informations sur TOUS les rôles sont-elles demandées TOUT le temps?
Il peut également arriver que l'utilisateur se connecte au tableau de bord et exécute 90% du temps des tâches liées au rôle «Ingénieur». L'intégration hybride pourrait être effectuée pour ce rôle particulier dans son intégralité et ne conserver que les références pour le reste.
Être sans schéma n'est pas seulement une caractéristique de NoSQL, cela pourrait être un avantage dans ce cas. Il est parfaitement valable d'imbriquer différents types d'objets dans la propriété «Roles» d'un objet utilisateur.
la source
dans le cas où l'employé et la société sont entité-objet, essayez d'utiliser le schéma suivant:
la source