Jak wykonać odpowiednik SQL Join w MongoDB?
Powiedzmy na przykład, że masz dwie kolekcje (użytkownicy i komentarze), a ja chcę pobrać wszystkie komentarze za pomocą pid = 444 wraz z informacjami dla każdego z nich.
comments
{ uid:12345, pid:444, comment="blah" }
{ uid:12345, pid:888, comment="asdf" }
{ uid:99999, pid:444, comment="qwer" }
users
{ uid:12345, name:"john" }
{ uid:99999, name:"mia" }
Czy istnieje sposób na wyciągnięcie wszystkich komentarzy z określonym polem (np. ... find ({pid: 444})) i informacji o użytkowniku związanych z każdym komentarzem za jednym razem?
W tej chwili najpierw otrzymuję komentarze, które pasują do moich kryteriów, a następnie ustalam wszystkie numery UID w tym zestawie wyników, pobieram obiekty użytkownika i łączę je z wynikami komentarza. Wygląda na to, że robię to źle.
Odpowiedzi:
Począwszy od wersji Mongo 3.2 odpowiedzi na to pytanie są w większości niepoprawne. Nowy operator wyszukiwania $ dodany do potoku agregacji jest zasadniczo identyczny jak lewe połączenie zewnętrzne:
https://docs.mongodb.org/master/reference/operator/aggregation/lookup/#pipe._S_lookup
Z dokumentów:
Oczywiście Mongo nie jest relacyjną bazą danych, a deweloperzy ostrożnie zalecają konkretne przypadki użycia dla wyszukiwania $, ale przynajmniej od 3.2 robienie łączenia jest teraz możliwe z MongoDB.
źródło
Ta strona na oficjalnej stronie mongodb zawiera dokładnie to pytanie:
https://mongodb-documentation.readthedocs.io/en/latest/ecosystem/tutorial/model-data-for-ruby-on-rails.html
źródło
Możemy scalić / połączyć wszystkie dane tylko w jednym zbiorze za pomocą prostej funkcji w kilku wierszach za pomocą konsoli klienta mongodb, a teraz możemy wykonać żądane zapytanie. Poniżej pełnego przykładu
.- Autorzy:
.- Kategorie:
.- Książki
.- Wypożyczanie książek
.- Magia:
.- Pobierz nowe dane kolekcji:
.- Odpowiedź :)
Mam nadzieję, że te linie mogą ci pomóc.
źródło
Musisz to zrobić tak, jak to opisałeś. MongoDB jest nierelacyjną bazą danych i nie obsługuje połączeń.
źródło
Jak zauważyli inni, próbujesz utworzyć relacyjną bazę danych z żadnej relacyjnej bazy danych, której tak naprawdę nie chcesz, ale tak czy inaczej, jeśli masz przypadek, że musisz to zrobić tutaj, jest to rozwiązanie, którego możesz użyć. Najpierw szukamy znaleziska w kolekcji A (lub w twoim przypadku użytkowników), a następnie otrzymujemy każdy przedmiot jako obiekt, a następnie używamy właściwości obiektu (w twoim przypadku) do wyszukiwania w naszej drugiej kolekcji (w komentarzach w twoim przypadku), jeśli możemy to znaleźć, wtedy mamy dopasowanie i możemy go wydrukować lub coś z tym zrobić. Mam nadzieję, że to ci pomoże i powodzenia :)
źródło
Z odpowiednią kombinacją $ lookup , $ project i $ match możesz łączyć tabele wielokrotne na wielu parametrach. Wynika to z tego, że można je łączyć wielokrotnie.
Załóżmy, że chcemy wykonać następujące czynności ( odniesienie )
Krok 1: Połącz wszystkie tabele
możesz wyszukać tyle tabel, ile chcesz.
wyszukiwanie $ - jeden dla każdej tabeli w zapytaniu
$ odpręż się - ponieważ dane są poprawnie zdenormalizowane, w przeciwnym razie są pakowane w tablice
Kod Python
Krok 2: Zdefiniuj wszystkie warunki warunkowe
projekt $ : zdefiniuj tutaj wszystkie instrukcje warunkowe oraz wszystkie zmienne, które chcesz wybrać.
Kod Python ..
Krok 3: Dołącz do wszystkich warunków warunkowych
$ match - dołącz do wszystkich warunków używając OR lub AND itd. Może być ich wiele.
$ projekt : nie zdefiniuj wszystkich warunków warunkowych
Kod Python ..
W ten sposób można wykonać prawie dowolną kombinację tabel, warunków i złączeń.
źródło
Oto przykład „dołączenia” * do kolekcji aktorów i filmów :
https://github.com/mongodb/cookbook/blob/master/content/patterns/pivot.txt
Wykorzystuje
.mapReduce()
metodę* join - alternatywa dla dołączania do baz danych zorientowanych na dokumenty
źródło
Możesz dołączyć do dwóch kolekcji w Mongo za pomocą odnośnika, który jest oferowany w wersji 3.2. W twoim przypadku byłoby to zapytanie
lub możesz również dołączyć w odniesieniu do użytkowników, wówczas nastąpi niewielka zmiana, jak podano poniżej.
Będzie działał tak samo jak lewy i prawy łączenie w SQL.
źródło
To zależy od tego, co próbujesz zrobić.
Obecnie masz skonfigurowaną znormalizowaną bazę danych, co jest w porządku, a sposób, w jaki to robisz, jest odpowiedni.
Istnieją jednak inne sposoby na zrobienie tego.
Możesz mieć kolekcję postów z osadzonymi komentarzami do każdego postu z odniesieniami do użytkowników, które możesz iteracyjnie zapytać o dostęp. Możesz przechowywać nazwę użytkownika z komentarzami, możesz przechowywać je wszystkie w jednym dokumencie.
W NoSQL chodzi o elastyczne schematy oraz bardzo szybkie czytanie i pisanie. W typowej farmie Big Data baza danych jest największym wąskim gardłem, masz mniej silników baz danych niż serwery aplikacji i front-end ... są one droższe, ale mocniejsze, a miejsce na dysku twardym jest stosunkowo tanie. Normalizacja bierze się z koncepcji oszczędzania miejsca, ale wiąże się z kosztem zmuszania baz danych do wykonywania skomplikowanych połączeń i sprawdzania integralności relacji, przeprowadzania operacji kaskadowych. Wszystko to oszczędza programistom problemów, jeśli właściwie zaprojektowali bazę danych.
W przypadku NoSQL, jeśli zaakceptujesz, że nadmiarowość i przestrzeń dyskowa nie są problemami ze względu na ich koszt (zarówno czas procesora wymagany do wykonania aktualizacji, jak i koszty dysku twardego do przechowywania dodatkowych danych), denormalizacja nie stanowi problemu (dla wbudowanych macierzy, które stają się setki tysięcy przedmiotów może to być problem z wydajnością, ale przez większość czasu to nie problem). Ponadto będziesz mieć kilka serwerów aplikacji i serwerów front-end dla każdego klastra bazy danych. Poproś ich, aby mocno podnieśli złączenia i pozwól serwerom bazy danych trzymać się odczytu i zapisu.
TL; DR: To, co robisz, jest w porządku, i są na to inne sposoby. Sprawdź wzorce modeli danych dokumentacji mongodb, aby znaleźć wspaniałe przykłady. http://docs.mongodb.org/manual/data-modeling/
źródło
Istnieje specyfikacja obsługiwana przez wiele sterowników, która nazywa się DBRef.
Zaczerpnięte z dokumentacji MongoDB: Modele danych> Odniesienie do modelu danych> Odniesienia do bazy danych
źródło
Wyszukiwanie $ (agregacja)
Wykonuje lewe zewnętrzne połączenie z niechronionym zbiorem w tej samej bazie danych, aby odfiltrować dokumenty z kolekcji „połączonej” w celu przetworzenia. Do każdego dokumentu wejściowego etap wyszukiwania $ dodaje nowe pole tablicy, którego elementami są pasujące dokumenty z kolekcji „połączonej”. Etap wyszukiwania $ przekazuje te przekształcone dokumenty do następnego etapu. Etap wyszukiwania $ ma następujące składnie:
Dopasowanie równości
Aby wykonać dopasowanie równości między polem z dokumentów wejściowych a polem z dokumentów z kolekcji „połączonej”, etap wyszukiwania $ ma następującą składnię:
Operacja odpowiadałaby następującej instrukcji pseudo-SQL:
URL Mongo
źródło
W wersjach wcześniejszych niż 3.2.6 Mongodb nie obsługuje kwerendy dołączającej, tak jak mysql. poniżej rozwiązanie, które działa dla Ciebie.
źródło
Możesz uruchamiać zapytania SQL, w tym dołączyć do MongoDB z mongo_fdw z Postgres.
źródło
MongoDB nie zezwala na łączenia, ale do obsługi tego można użyć wtyczek. Sprawdź wtyczkę mongo-join. Jest najlepszy i już go użyłem. Możesz zainstalować go bezpośrednio za pomocą npm
npm install mongo-join
. Możesz sprawdzić pełną dokumentację z przykładami .(++) naprawdę pomocne narzędzie, gdy musimy dołączyć do (N) kolekcji
(-) możemy zastosować warunki tylko na najwyższym poziomie zapytania
Przykład
źródło
Możesz to zrobić za pomocą potoku agregacji, ale pisanie go samemu jest trudne.
Możesz użyć
mongo-join-query
do automatycznego utworzenia potoku agregacji na podstawie zapytania.Tak wyglądałoby Twoje zapytanie:
Twój wynik uzyska obiekt użytkownika w
uid
polu i możesz połączyć tyle poziomów, ile chcesz. Możesz wypełnić odniesienie do użytkownika, który odnosi się do zespołu, który odnosi się do czegoś innego itp.Uwaga : Napisałem,
mongo-join-query
aby rozwiązać dokładnie ten problem.źródło
playORM może to zrobić za pomocą S-SQL (Scalable SQL), który po prostu dodaje partycjonowanie, dzięki czemu możesz wykonywać sprzężenia wewnątrz partycji.
źródło
Nie, to nie wygląda na to, że robisz to źle. Połączenia MongoDB odbywają się „po stronie klienta”. Prawie tak jak powiedziałeś:
To nie jest „prawdziwe” łączenie, ale w rzeczywistości jest o wiele bardziej przydatne niż łączenie SQL, ponieważ nie musisz zajmować się duplikatami wierszy dla „wielu” złączeń, zamiast dekorowania pierwotnie wybranego zestawu.
Na tej stronie jest wiele bzdur i FUD. Okazuje się, że 5 lat później MongoDB to wciąż coś.
źródło
Myślę, że jeśli potrzebujesz znormalizowanych tabel danych - musisz wypróbować inne rozwiązania baz danych.
Ale ja popieram to rozwiązanie dla MOngo na Git Przy okazji, wstawia kod - ma nazwę filmu, ale identyfikator filmu noi .
Problem
Masz kolekcję aktorów z szeregiem filmów, które zrobili.
Chcesz wygenerować kolekcję filmów z zestawem aktorów w każdym z nich.
Niektóre przykładowe dane
Rozwiązanie
Musimy przeglądać każdy film w dokumencie aktora i emitować każdy film osobno.
Połów tutaj znajduje się w fazie redukcji. Nie możemy wyemitować tablicy z fazy redukcji, dlatego musimy zbudować tablicę aktorów w zwracanym dokumencie „wartość”.
KodZauważ, że lista aktorów jest w rzeczywistości obiektem javascript zawierającym tablicę. Zauważ też, że mapa emituje tę samą strukturę.
Uruchom następujące polecenie, aby wykonać mapę / zmniejszyć, wyślij ją do kolekcji „przestawnej” i wydrukuj wynik:
printjson (db.actors.mapReduce (mapuj, zmniejsz, „przestaw”)); db.pivot.find (). forEach (printjson);
Oto przykładowe wyniki. Zauważ, że „Pretty Woman” i „Runaway Bride” mają zarówno „Richarda Gere”, jak i „Julię Roberts”.
źródło
Możemy połączyć dwie kolekcje za pomocą zapytania podrzędnego mongoDB. Oto przykład: Komentarze--
Userss--
Zapytanie podrzędne MongoDB dla JOIN--
Uzyskaj wynik z nowo wygenerowanej kolekcji
Wynik--
Mam nadzieję, że to pomoże.
źródło