Pour créer une relation dans MongoDB, intégrez un document BSON dans un autre ou référencez-le à partir d'un autre.
Les bases de données MongoDB fonctionnent différemment des bases de données relationnelles. Cela vaut également pour les relations.
Dans MongoDB, vous pouvez créer une relation en utilisant l'une des deux méthodes suivantes :
- Documents intégrés.
- Documents référencés.
La méthode que vous utiliserez dépendra des données et de la manière dont vous avez l'intention d'interroger ces données.
Relations intégrées
Avec MongoDB, vous pouvez intégrer des documents dans des documents. Par conséquent, un seul document peut contenir ses propres relations.
En fait, nous avons déjà créé une relation en utilisant cette méthode lorsque nous avons créé un document pour la première fois.
Relation individuelle
Une relation individuelle est l'endroit où le document parent a un enfant et l'enfant a un parent.
Par exemple, une règle métier peut indiquer qu'un artiste ne peut avoir qu'une seule adresse et que l'adresse ne peut appartenir qu'à un seul artiste.
Le code suivant crée une relation un-à-un, intégrée dans le document.
db.artists.insert( { _id : 2, artistname : "Prince", address : { street : "Audubon Road", city : "Chanhassen", state : "Minnesota", country : "United States" } } )
Résultat :
WriteResult({ "nInserted" : 1 })
Relation un-à-plusieurs
Un un-à-plusieurs relation est l'endroit où le document parent peut avoir plusieurs documents enfants, mais les documents enfants ne peuvent avoir qu'un seul document parent.
Ainsi, une autre règle commerciale pourrait dire qu'un artiste peut avoir plusieurs albums, mais qu'un album ne peut appartenir qu'à un seul artiste.
L'exécution du code suivant créera une relation un-à-plusieurs :
db.artists.insert( { _id : 3, artistname : "Moby", albums : [ { album : "Play", year : 1999, genre : "Electronica" }, { album : "Long Ambients 1: Calm. Sleep.", year : 2016, genre : "Ambient" } ] } )
Résultat :
WriteResult({ "nInserted" : 1 })
Relations référencées dans les documents
Vous pouvez utiliser une référence de document pour créer une relation. Plutôt que d'intégrer le document enfant dans le document parent (comme nous l'avons fait ci-dessus), vous séparez le document enfant dans son propre document autonome.
Nous pourrions donc faire ceci :
Document parent
db.artists.insert( { _id : 4, artistname : "Rush" } )
Documents enfants
Nous allons insérer 3 documents enfants, un pour chaque membre du groupe :
db.musicians.insert( { _id : 9, name : "Geddy Lee", instrument : [ "Bass", "Vocals", "Keyboards" ], artist_id : 4 } )
db.musicians.insert( { _id : 10, name : "Alex Lifeson", instrument : [ "Guitar", "Backing Vocals" ], artist_id : 4 } )
db.musicians.insert( { _id : 11, name : "Neil Peart", instrument : "Drums", artist_id : 4 } )
Interroger la relation
Après avoir inséré les deux documents ci-dessus, vous pouvez utiliser $lookup
pour effectuer une jointure externe gauche sur les deux collections.
Ceci, en conjonction avec le aggregate()
méthode et $match
pour spécifier l'artiste spécifique qui vous intéresse, renverra les documents parent et enfant en un.
db.artists.aggregate([ { $lookup: { from: "musicians", localField: "_id", foreignField: "artist_id", as: "band_members" } }, { $match : { artistname : "Rush" } } ]).pretty()
Résultat :
{ "_id" : 4, "artistname" : "Rush", "band_members" : [ { "_id" : 9, "name" : "Geddy Lee", "instrument" : [ "Bass", "Vocals", "Keyboards" ], "artist_id" : 4 }, { "_id" : 10, "name" : "Alex Lifeson", "instrument" : [ "Guitar", "Backing Vocals" ], "artist_id" : 4 }, { "_id" : 11, "name" : "Neil Peart", "instrument" : "Drums", "artist_id" : 4 } ] }
Vous pouvez voir que les deux premiers champs proviennent de la collection des artistes et que le reste provient de la collection des musiciens.
Donc, si vous n'interrogez que la collection d'artistes par elle-même :
db.artists.find( { artistname : "Rush" } )
Vous n'obtiendrez que ceci :
{ "_id" : 4, "artistname" : "Rush" }
Aucune donnée associée n'est renvoyée.
Quand utiliser les documents intégrés par rapport aux documents référencés
Les deux méthodes de création de relations ont leurs avantages et leurs inconvénients. Il peut arriver que vous utilisiez des documents intégrés et d'autres fois que vous utilisiez des documents référencés.
Quand utiliser les relations intégrées
L'un des principaux avantages de l'utilisation de la méthode de relation intégrée est la performance. Lorsque la relation est intégrée au document, les requêtes s'exécutent plus rapidement que si elles étaient réparties sur plusieurs documents. MongoDB n'a besoin de renvoyer qu'un seul document, plutôt que de joindre plusieurs documents afin de récupérer les relations. Cela peut améliorer considérablement les performances, en particulier lorsque vous travaillez avec de nombreuses données.
Les relations intégrées facilitent également l'écriture des requêtes. Plutôt que d'écrire des requêtes complexes qui joignent de nombreux documents via leur identifiant unique, vous pouvez renvoyer toutes les données associées dans une seule requête.
Une autre considération à garder à l'esprit est que MongoDB ne peut garantir l'atomicité qu'au niveau du document. Les mises à jour de documents pour un seul document sont toujours atomiques, mais pas pour plusieurs documents.
Lorsque plusieurs utilisateurs accèdent aux données, il est toujours possible que deux utilisateurs ou plus essaient de mettre à jour le même document avec des données différentes. Dans ce cas, MongoDB s'assurera qu'aucun conflit ne se produit et qu'un seul ensemble de données est mis à jour à la fois. MongoDB ne peut pas garantir cela sur plusieurs documents.
Ainsi, en général, les relations intégrées peuvent être utilisées dans la plupart des cas, tant que le document reste dans la limite de taille (16 mégaoctets au moment de la rédaction) et/ou sa limite d'imbrication (100 niveaux de profondeur au moment de la rédaction).
Cependant, les relations intégrées ne conviennent pas à tous reprises. Il peut y avoir des situations où il est plus logique de créer une relation référencée par un document.
Quand utiliser les relations référencées
Pour les données qui doivent être répétées dans de nombreux documents, il peut être utile de les avoir dans leur propre document séparé. Cela peut réduire les erreurs et aider à maintenir la cohérence des données (tout en gardant à l'esprit que les mises à jour de plusieurs documents ne sont pas atomiques).
En utilisant l'exemple ci-dessus, un musicien peut être membre (ou ex-membre) de plusieurs groupes. Certains pourraient également produire des albums pour d'autres artistes, enseigner aux étudiants, organiser des cliniques, etc. De plus, de nombreuses données pourraient être stockées pour chaque musicien. Il est donc logique d'avoir un document séparé pour chaque musicien dans ce cas.
De plus, si vous pensez que vos documents intégrés peuvent dépasser la limite de taille de fichier imposée par MongoDB, vous devrez stocker certaines données dans des documents séparés.