Jak mogę (w MongoDB) łączyć dane z wielu kolekcji w jedną kolekcję?
Czy mogę użyć funkcji zmniejszania mapy, a jeśli tak, to w jaki sposób?
Byłbym bardzo wdzięczny za jakiś przykład, ponieważ jestem nowicjuszem.
mongodb
mongodb-query
aggregation-framework
użytkownik697697
źródło
źródło
db.collection1.find().forEach(function(doc){db.collection2.save(doc)});
wystarczy. Podaj używany sterownik (java, php, ...), jeśli nie korzystasz z powłoki mongo.Odpowiedzi:
Chociaż nie można tego robić w czasie rzeczywistym, można wielokrotnie uruchamiać funkcję zmniejszania mapy w celu scalenia danych za pomocą opcji „zmniejszania” w MongoDB 1.8+ map / zmniejsz (patrz http://www.mongodb.org/ display / DOCS / MapReduce # MapReduce-Outputoptions ). Musisz mieć klucz w obu kolekcjach, którego możesz użyć jako _id.
Załóżmy na przykład, że masz
users
kolekcję icomments
kolekcję i chcesz mieć nową kolekcję, która zawiera informacje demograficzne użytkownika dla każdego komentarza.Powiedzmy, że
users
kolekcja ma następujące pola:A następnie
comments
kolekcja ma następujące pola:Zrobiłbyś tę mapę / zmniejszyć:
W tym momencie będziesz mieć nową kolekcję o nazwie,
users_comments
która zawiera scalone dane i możesz teraz z niej korzystać. Wszystkie te zredukowane kolekcje mają_id
klucz, który emitowałeś w funkcjach mapy, a następnie wszystkie wartości są podkluczem wewnątrzvalue
klucza - wartości nie znajdują się na najwyższym poziomie tych zredukowanych dokumentów.To jest dość prosty przykład. Możesz to powtórzyć z większą liczbą kolekcji, tak długo jak chcesz kontynuować tworzenie zmniejszonej kolekcji. Możesz także tworzyć podsumowania i agregacje danych. Prawdopodobnie zdefiniowałbyś więcej niż jedną funkcję redukującą, ponieważ logika agregacji i zachowania istniejących pól staje się bardziej złożona.
Zauważysz również, że dla każdego użytkownika jest teraz jeden dokument z wszystkimi komentarzami tego użytkownika w tablicy. Gdybyśmy scalali dane, które mają relację jeden-do-jednego, a nie jeden-do-wielu, byłoby to płaskie i można po prostu użyć funkcji redukcji w ten sposób:
Jeśli chcesz spłaszczyć
users_comments
kolekcję, aby był to jeden dokument na komentarz, uruchom dodatkowo:Ta technika zdecydowanie nie powinna być wykonywana w locie. Nadaje się do zadania cron lub czegoś takiego, co okresowo aktualizuje scalone dane. Prawdopodobnie będziesz chciał uruchomić
ensureIndex
nową kolekcję, aby upewnić się, że zapytania, które wykonujesz przeciwko niej, działają szybko (pamiętaj, że twoje dane są nadal wvalue
kluczu, więc jeśli indeksowałbyś czascomments_with_demographics
komentowaniacreated
, byłoby todb.comments_with_demographics.ensureIndex({"value.created": 1});
źródło
users_comments
kolekcji po pierwszym bloku kodu gist.github.com/nolanamy/83d7fb6a9bf92482a1c4311ad9c78835MongoDB 3.2 pozwala teraz łączyć dane z wielu kolekcji w jedną poprzez etap agregacji wyszukiwania $ . Jako praktyczny przykład, powiedzmy, że masz dane o książkach podzielone na dwie różne kolekcje.
Pierwszy zbiór, nazywany
books
, zawierający następujące dane:I druga kolekcja, nazywana
books_selling_data
, zawierająca następujące dane:Aby połączyć obie kolekcje, wystarczy po prostu użyć $ lookup w następujący sposób:
Po tej agregacji
books
kolekcja będzie wyglądać następująco:Ważne jest, aby zwrócić uwagę na kilka rzeczy:
books_selling_data
nie można podzielić kolekcji „z” .Podsumowując, jeśli chcesz skonsolidować obie kolekcje, mając w tym przypadku płaskie pole copy_sold z całkowitą liczbą sprzedanych kopii, będziesz musiał pracować trochę więcej, prawdopodobnie używając kolekcji pośredniej, która następnie być $ się do ostatecznego odbioru.
źródło
$lookup
czy wszystkie „localField” i „ForeignField” nie powinny być równe „isbn”? nie „_id” i „isbn”?Jeśli nie ma wstawiania zbiorczego do mongodb, zapętlamy wszystkie obiekty w
small_collection
i wstawiamy je jeden po drugim dobig_collection
:źródło
Bardzo prosty przykład z wyszukiwaniem $.
Tutaj jest używany
Zamiast
Ponieważ {$ unwind: "$ userRoleData"} zwróci pusty lub wynik 0, jeśli nie znaleziono pasującego rekordu przy wyszukiwaniu $.
źródło
Tworzenie związków w MongoDB w sposób „SQL UNION” jest możliwe przy użyciu agregacji wraz z odnośnikami w jednym zapytaniu. Oto przykład, który przetestowałem, który działa z MongoDB 4.0:
Oto wyjaśnienie, jak to działa:
Instancję
aggregate
Spośród każdej kolekcji swojej bazie danych, która ma co najmniej jeden dokument w nim. Jeśli nie możesz zagwarantować, że jakakolwiek kolekcja Twojej bazy danych nie będzie pusta, możesz obejść ten problem, tworząc w bazie danych pewnego rodzaju „obojętny” zbiór zawierający pojedynczy pusty dokument, który będzie tam specjalnie do wykonywania zapytań dotyczących związków.Zrób pierwszy etap swojego rurociągu
{ $limit: 1 }
. Spowoduje to usunięcie wszystkich dokumentów z kolekcji oprócz pierwszego.Usuń wszystkie pola z pozostałego dokumentu za pomocą
$project
etapu:Twój agregat zawiera teraz pojedynczy, pusty dokument. Czas dodać wyszukiwania dla każdej kolekcji, którą chcesz połączyć. Możesz użyć tego
pipeline
pola, aby wykonać określone filtrowanie, lub pozostawićlocalField
iforeignField
zerować, aby dopasować całą kolekcję.Masz teraz agregat zawierający pojedynczy dokument zawierający 3 tablice takie jak to:
Następnie możesz scalić je razem w jedną tablicę przy użyciu stołu
$project
montażowego wraz z$concatArrays
operatorem agregacji:Masz teraz agregat zawierający pojedynczy dokument, w którym znajduje się tablica zawierająca twoją unię kolekcji. Co pozostaje do zrobienia jest dodanie
$unwind
i na$replaceRoot
scenę, aby podzielić swoją tablicę w oddzielnych dokumentach:Voilà. Masz teraz zestaw wyników zawierający kolekcje, które chcesz połączyć ze sobą. Następnie możesz dodać kolejne etapy, aby dalej filtrować, sortować, stosować skip () i limit (). Prawie wszystko, co chcesz.
źródło
użyj wielu $ lookup dla wielu kolekcji w agregacji
pytanie:
wynik:
źródło
Mongorestore ma tę funkcję dołączania do wszystkiego, co jest już w bazie danych, więc to zachowanie można wykorzystać do łączenia dwóch kolekcji:
Nie próbowałem tego jeszcze, ale może działać szybciej niż podejście do mapy / zmniejszania.
źródło
Zaczynając
Mongo 4.4
, możemy osiągnąć to połączenie w ramach potoku agregacji, łącząc nowy$unionWith
etap agregacji z$group
nowym$accumulator
operatorem:$unionWith
łączy rekordy z danej kolekcji w dokumentach już w potoku agregacji. Po 2 etapach związkowych mamy zatem wszystkich użytkowników, książki i nagrania filmowe w przygotowaniu.Następnie
$group
rejestrujemy$user
i gromadzimy elementy za pomocą$accumulator
operatora, umożliwiając niestandardowe gromadzenie dokumentów podczas ich grupowania:accumulateArgs
.init
określa stan, który będzie się kumulował, gdy grupujemy elementy.accumulate
funkcja umożliwia wykonywanie akcja niestandardowa z rekordem są grupowane w celu zbudowania nagromadzony stan. Na przykład, jeśli element zgrupowany mabook
zdefiniowane pole, wówczas aktualizujemybooks
część stanu.merge
służy do łączenia dwóch stanów wewnętrznych. Jest używany tylko w przypadku agregacji działających na dzielonych klastrach lub gdy operacja przekracza limity pamięci.źródło
Tak, możesz: skorzystaj z tej funkcji narzędzia, którą napisałem dzisiaj:
Możesz przekazać do tej funkcji dowolną liczbę kolekcji, pierwsza będzie docelowa. Wszystkie pozostałe kolekcje są źródłami, które należy przenieść do kolekcji docelowej.
źródło
Fragment kodu. Dzięki uprzejmości wiele postów na przepełnieniu stosu, w tym ten.
źródło
Musisz to zrobić w warstwie aplikacji. Jeśli używasz ORM, może użyć adnotacji (lub czegoś podobnego), aby pobrać odniesienia istniejące w innych kolekcjach. Pracowałem tylko z Morphia , a
@Reference
adnotacja pobiera przywoływany byt, gdy jest pytany, więc jestem w stanie uniknąć robienia tego samemu w kodzie.źródło