Als u een relatie in MongoDB wilt maken, sluit u een BSON-document in een ander document in of verwijst u ernaar vanuit een ander document.
MongoDB-databases werken anders dan relationele databases. Dit geldt ook voor relaties.
In MongoDB kunt u een relatie maken met een van de volgende twee methoden:
- Ingesloten documenten.
- Documenten waarnaar wordt verwezen.
De methode die u gebruikt, hangt af van de gegevens en hoe u die gegevens wilt opvragen.
Ingesloten relaties
Met MongoDB kunt u documenten insluiten in documenten. Daarom kan een enkel document zijn eigen relaties bevatten.
In feite hebben we al een relatie gemaakt met deze methode toen we voor het eerst een document maakten.
Een-op-een-relatie
Een een-op-een relatie is waar het bovenliggende document één kind heeft en het kind één ouder.
Een bedrijfsregel zou bijvoorbeeld kunnen zeggen dat een artiest maar één adres mag hebben en dat het adres maar van één artiest kan zijn.
De volgende code creëert een één-op-één relatie, ingebed in het document.
db.artists.insert( { _id : 2, artistname : "Prince", address : { street : "Audubon Road", city : "Chanhassen", state : "Minnesota", country : "United States" } } )
Resultaat:
WriteResult({ "nInserted" : 1 })
Een-op-veel-relatie
Een een-op-veel relatie is waar het bovenliggende document veel onderliggende documenten kan hebben, maar de onderliggende documenten kunnen slechts één bovenliggend document hebben.
Een andere bedrijfsregel zou dus kunnen zeggen dat één artiest veel albums kan hebben, maar dat een album maar aan één artiest kan toebehoren.
Als u de volgende code uitvoert, ontstaat er een een-op-veel-relatie:
db.artists.insert( { _id : 3, artistname : "Moby", albums : [ { album : "Play", year : 1999, genre : "Electronica" }, { album : "Long Ambients 1: Calm. Sleep.", year : 2016, genre : "Ambient" } ] } )
Resultaat:
WriteResult({ "nInserted" : 1 })
Document waarnaar wordt verwezen relaties
U kunt een documentverwijzing gebruiken om een relatie aan te maken. In plaats van het onderliggende document in te sluiten in het bovenliggende document (zoals we hierboven hebben gedaan), scheidt u het onderliggende document in een eigen op zichzelf staand document.
Dus we zouden dit kunnen doen:
Ouderdocument
db.artists.insert( { _id : 4, artistname : "Rush" } )
Kinddocumenten
We voegen 3 onderliggende documenten in — één voor elk bandlid:
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 } )
De relatie opvragen
Na het invoegen van de bovenstaande twee documenten, kunt u $lookup
. gebruiken om een left outer join uit te voeren op de twee collecties.
Dit, in combinatie met de aggregate()
methode, en $match
om de specifieke artiest waarin u geïnteresseerd bent te specificeren, retourneert u ouder- en kinddocumenten in één.
db.artists.aggregate([ { $lookup: { from: "musicians", localField: "_id", foreignField: "artist_id", as: "band_members" } }, { $match : { artistname : "Rush" } } ]).pretty()
Resultaat:
{ "_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 } ] }
Je kunt zien dat de eerste twee velden uit de artiestencollectie komen en de rest uit de muzikantencollectie.
Dus als je alleen de artiestencollectie opvraagt:
db.artists.find( { artistname : "Rush" } )
Je krijgt alleen dit:
{ "_id" : 4, "artistname" : "Rush" }
Er worden geen gerelateerde gegevens geretourneerd.
Wanneer ingesloten documenten gebruiken versus documenten waarnaar wordt verwezen
Beide methoden om relaties aan te gaan hebben hun voor- en nadelen. Soms gebruikt u ingesloten documenten en soms gebruikt u documenten waarnaar wordt verwezen.
Wanneer ingesloten relaties gebruiken
Een van de belangrijkste voordelen van het gebruik van de embedded-relatiemethode is de prestatie. Wanneer de relatie is ingesloten in het document, zullen query's sneller worden uitgevoerd dan wanneer ze over meerdere documenten zouden zijn verspreid. MongoDB hoeft alleen het ene document te retourneren, in plaats van meerdere documenten samen te voegen om de relaties op te halen. Dit kan een grote prestatieverbetering opleveren, vooral wanneer u met veel gegevens werkt.
Ingesloten relaties maken query's ook gemakkelijker om te schrijven. In plaats van complexe query's te schrijven die via hun unieke ID aan veel documenten worden gekoppeld, kunt u alle gerelateerde gegevens in één enkele query retourneren.
Een andere overweging om in gedachten te houden is dat MongoDB alleen atomiciteit op documentniveau kan garanderen. Documentupdates voor een enkel document zijn altijd atomair, maar niet voor meerdere documenten.
Wanneer meerdere gebruikers toegang hebben tot de gegevens, is er altijd een kans dat twee of meer gebruikers hetzelfde document met verschillende gegevens proberen bij te werken. In dit geval zorgt MongoDB ervoor dat er geen conflicten optreden en dat er slechts één set gegevens tegelijk wordt bijgewerkt. MongoDB kan dit niet voor meerdere documenten garanderen.
Dus in het algemeen kunnen ingesloten relaties in de meeste gevallen worden gebruikt, zolang het document binnen de limiet blijft (16 megabytes op het moment van schrijven) en/of de nestinglimiet (100 niveaus diep op het moment van schrijven).
Ingesloten relaties zijn echter niet geschikt voor alle gelegenheden. Er kunnen situaties zijn waarin het zinvoller is om een document waarnaar wordt verwezen, een relatie te creëren.
Wanneer referentierelaties gebruiken
Voor gegevens die in veel documenten moeten worden herhaald, kan het handig zijn om ze in hun eigen afzonderlijke document te hebben. Dit kan fouten verminderen en helpen om de gegevens consistent te houden (terwijl u er rekening mee houdt dat updates van meerdere documenten niet atomair zijn).
Met het bovenstaande voorbeeld kan een muzikant lid (of ex-lid) zijn van veel bands. Sommigen produceren misschien ook albums voor andere artiesten, geven les aan studenten, geven clinics, enz. Er kunnen ook veel gegevens over elke muzikant worden opgeslagen. Dus in dit geval is het zinvol om voor elke muzikant een apart document te hebben.
Als u ook denkt dat uw ingesloten documenten de door MongoDB opgelegde maximale bestandsgrootte overschrijden, moet u enkele gegevens in afzonderlijke documenten opslaan.