Aby utworzyć relację w MongoDB, osadź dokument BSON w innym dokumencie lub odwołaj się do niego z innego.
Bazy danych MongoDB działają inaczej niż relacyjne bazy danych. Dotyczy to również relacji.
W MongoDB możesz utworzyć relację za pomocą jednej z dwóch następujących metod:
- Osadzone dokumenty.
- Dokumenty odniesienia.
Metoda, której użyjesz, będzie zależeć od danych i tego, w jaki sposób zamierzasz przeszukiwać te dane.
Wbudowane relacje
Dzięki MongoDB możesz osadzać dokumenty w dokumentach. Dlatego pojedynczy dokument może zawierać własne relacje.
W rzeczywistości stworzyliśmy już relację przy użyciu tej metody, kiedy po raz pierwszy tworzyliśmy dokument.
Relacja jeden-do-jednego
relacja jeden-do-jednego to miejsce, w którym dokument nadrzędny ma jedno dziecko, a dziecko ma jednego rodzica.
Na przykład reguła biznesowa może mówić, że artysta może mieć tylko jeden adres i że adres może należeć tylko do jednego artysty.
Poniższy kod tworzy relację jeden do jednego, osadzoną w dokumencie.
db.artists.insert( { _id : 2, artistname : "Prince", address : { street : "Audubon Road", city : "Chanhassen", state : "Minnesota", country : "United States" } } )
Wynik:
WriteResult({ "nInserted" : 1 })
Relacja jeden-do-wielu
jeden do wielu relacja polega na tym, że dokument nadrzędny może zawierać wiele dokumentów podrzędnych, ale dokumenty podrzędne mogą mieć tylko jeden dokument nadrzędny.
Inna zasada biznesowa może więc mówić, że jeden artysta może mieć wiele albumów, ale album może należeć tylko do jednego artysty.
Uruchomienie następującego kodu spowoduje utworzenie relacji jeden-do-wielu:
db.artists.insert( { _id : 3, artistname : "Moby", albums : [ { album : "Play", year : 1999, genre : "Electronica" }, { album : "Long Ambients 1: Calm. Sleep.", year : 2016, genre : "Ambient" } ] } )
Wynik:
WriteResult({ "nInserted" : 1 })
Powiązania z dokumentami
Możesz użyć odniesienia do dokumentu, aby utworzyć relację. Zamiast osadzić dokument podrzędny w dokumencie nadrzędnym (tak jak to zrobiliśmy powyżej), oddzielasz dokument podrzędny do osobnego dokumentu.
Więc możemy to zrobić:
Dokument nadrzędny
db.artists.insert( { _id : 4, artistname : "Rush" } )
Dokumenty podrzędne
Wstawimy 3 dokumenty podrzędne — po jednym dla każdego członka zespołu:
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 } )
Zapytanie o związek
Po wstawieniu powyższych dwóch dokumentów możesz użyć $lookup
wykonać lewe sprzężenie zewnętrzne na dwóch kolekcjach.
To w połączeniu z aggregate()
metoda i $match
aby określić konkretnego artystę, którym jesteś zainteresowany, zwróci dokumenty rodzica i dziecka w jednym.
db.artists.aggregate([ { $lookup: { from: "musicians", localField: "_id", foreignField: "artist_id", as: "band_members" } }, { $match : { artistname : "Rush" } } ]).pretty()
Wynik:
{ "_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 } ] }
Widać, że pierwsze dwa pola pochodzą z kolekcji artystów, a reszta z kolekcji muzyków.
Jeśli więc zapytasz tylko o samą kolekcję wykonawców:
db.artists.find( { artistname : "Rush" } )
Otrzymasz tylko to:
{ "_id" : 4, "artistname" : "Rush" }
Żadne powiązane dane nie są zwracane.
Kiedy używać dokumentów osadzonych a dokumentów referencyjnych
Obie metody tworzenia relacji mają swoje plusy i minusy. Czasami możesz użyć dokumentów osadzonych, a innym razem będziesz korzystać z dokumentów referencyjnych.
Kiedy używać wbudowanych relacji
Jedną z głównych korzyści wynikających z zastosowania metody relacji osadzonych jest wydajność. Gdy relacja jest osadzona w dokumencie, zapytania będą działać szybciej, niż gdyby były rozłożone na wiele dokumentów. MongoDB musi zwrócić tylko jeden dokument, zamiast łączyć wiele dokumentów w celu odzyskania relacji. Może to zapewnić znaczny wzrost wydajności — zwłaszcza podczas pracy z dużą ilością danych.
Osadzone relacje ułatwiają również pisanie zapytań. Zamiast pisać złożone zapytania, które łączą wiele dokumentów za pomocą ich unikalnego identyfikatora, możesz zwrócić wszystkie powiązane dane w ramach jednego zapytania.
Inną kwestią, o której należy pamiętać, jest to, że MongoDB może zapewnić niepodzielność tylko na poziomie dokumentu. Aktualizacje dokumentów dla jednego dokumentu są zawsze niepodzielne, ale nie dla wielu dokumentów.
Gdy wielu użytkowników uzyskuje dostęp do danych, zawsze istnieje szansa, że dwóch lub więcej użytkowników spróbuje zaktualizować ten sam dokument różnymi danymi. W takim przypadku MongoDB zapewni, że nie wystąpi konflikt i tylko jeden zestaw danych będzie aktualizowany na raz. MongoDB nie może tego zapewnić w wielu dokumentach.
Ogólnie rzecz biorąc, w większości przypadków można używać relacji osadzonych, o ile dokument mieści się w limicie rozmiaru (16 megabajtów w momencie pisania) i/lub limicie zagnieżdżenia (100 poziomów w momencie pisania).
Jednak osadzone relacje nie są odpowiednie dla wszystkich okazje. Mogą zaistnieć sytuacje, w których bardziej sensowne jest utworzenie relacji, do której odwołuje się dokument.
Kiedy używać relacji referencyjnych
W przypadku danych, które muszą być powtarzane w wielu dokumentach, pomocne może być umieszczenie ich w osobnym dokumencie. Może to zmniejszyć błędy i pomóc w utrzymaniu spójności danych (pamiętając, że aktualizacje wielu dokumentów nie są atomowe).
Korzystając z powyższego przykładu, jeden muzyk może być członkiem (lub byłym członkiem) wielu zespołów. Niektórzy mogą również produkować albumy dla innych artystów, uczyć studentów, prowadzić kliniki itp. Ponadto można przechowywać wiele danych dotyczących każdego muzyka. Dlatego w tym przypadku sensowne jest posiadanie osobnego dokumentu dla każdego muzyka.
Ponadto, jeśli uważasz, że Twoje osadzone dokumenty mogą przekraczać limit rozmiaru pliku nałożony przez MongoDB, będziesz musiał przechowywać niektóre dane w osobnych dokumentach.