Jak utworzyłbyś powiązanie wiele do wielu z MongoDB?
Na przykład; powiedzmy, że masz tabelę użytkowników i tabelę ról. Użytkownicy mają wiele ról, a role mają wielu użytkowników. W krainie SQL utworzyłbyś tabelę UserRoles.
Users:
Id
Name
Roles:
Id
Name
UserRoles:
UserId
RoleId
Jak jest obsługiwany ten sam rodzaj relacji w MongoDB?
many-to-many
associations
mongodb
Josh Close
źródło
źródło
Odpowiedzi:
W zależności od potrzeb zapytania możesz umieścić wszystko w dokumencie użytkownika:
Aby zdobyć wszystkich Inżynierów, użyj:
Jeśli chcesz zachować role w oddzielnych dokumentach, możesz dołączyć identyfikator _id dokumentu do tablicy ról zamiast nazwy:
i skonfiguruj role takie jak:
źródło
Zamiast próbować modelować zgodnie z naszym wieloletnim doświadczeniem z systemami RDBMS, okazało się, że znacznie łatwiej jest modelować rozwiązania repozytoriów dokumentów przy użyciu MongoDB, Redis i innych magazynów danych NoSQL, optymalizując pod kątem przypadków użycia odczytu, jednocześnie biorąc pod uwagę atomowe operacje zapisu, które muszą być obsługiwane przez przypadki użycia zapisu.
Na przykład zastosowania domeny „Użytkownicy w rolach” są następujące:
Można to modelować za pomocą następujących szablonów dokumentów:
W celu obsługi zastosowań o dużej częstotliwości, takich jak funkcje związane z rolami z jednostki użytkownika, użytkownik.Role są celowo zdenormalizowane, przechowywane zarówno w przypadku użytkownika, jak i roli. Użytkowników posiadających zduplikowaną pamięć.
Jeśli nie jest to wyraźnie widoczne w tekście, ale taki sposób myślenia jest zalecany podczas korzystania z repozytoriów dokumentów.
Mam nadzieję, że pomoże to wypełnić lukę w odniesieniu do czytelniczej strony operacji.
Jeśli chodzi o pisanie, zachęca się do modelowania zgodnie z pismami atomowymi. Na przykład, jeśli struktury dokumentów wymagają uzyskania blokady, zaktualizowania jednego dokumentu, następnie innego i prawdopodobnie większej liczby dokumentów, a następnie zwolnienia blokady, prawdopodobnie model zawiódł. To, że możemy budować rozproszone blokady, nie oznacza, że mamy ich używać.
W przypadku modelu User in Roles operacjami, które rozciągają nasze unikanie blokad przed zapisem atomowym, jest dodanie lub usunięcie użytkownika z roli. W obu przypadkach pomyślna operacja skutkuje zaktualizowaniem zarówno jednego użytkownika, jak i jednego dokumentu roli. Jeśli coś się nie powiedzie, łatwo jest przeprowadzić czyszczenie. Jest to jeden z powodów, dla których wzorzec jednostki pracy pojawia się często, gdy używane są repozytoria dokumentów.
Operacją, która naprawdę rozciąga nasze unikanie blokad zapisu atomowego, jest wyczyszczenie roli, co spowodowałoby wiele aktualizacji użytkownika w celu usunięcia Role.name z tablicy User.roles. Ta operacja czyszczenia jest generalnie odradzana, ale w razie potrzeby można ją wykonać, zlecając operacje:
W przypadku problemu, który najprawdopodobniej wystąpi w kroku 2, wycofanie jest łatwe, ponieważ ten sam zestaw nazw użytkowników z kroku 1 może być użyty do odzyskania lub kontynuowania.
źródło
Właśnie natknąłem się na to pytanie i chociaż jest stare, pomyślałem, że warto dodać kilka możliwości nie wymienionych w udzielonych odpowiedziach. W ciągu ostatnich kilku lat sytuacja nieco się zmieniła, dlatego warto podkreślić, że SQL i NoSQL zbliżają się do siebie.
Jeden z komentatorów poruszył mądrą ostrożną postawę, że „jeśli dane są relacyjne, używaj relacyjności”. Jednak ten komentarz ma sens tylko w świecie relacji, gdzie schematy zawsze poprzedzają aplikację.
ŚWIAT RELACYJNY : Dane strukturalne> Napisz aplikację, aby ją otrzymać
NOSQL WORLD: Zaprojektuj aplikację> Odpowiednio skonstruuj dane
Nawet jeśli dane są relacyjne, NoSQL jest nadal opcją. Na przykład relacje jeden do wielu nie stanowią żadnego problemu i są szeroko omówione w dokumentach MongoDB
ROZWIĄZANIE PROBLEMU Z ROKU 2010
Odkąd opublikowano to pytanie, podjęto poważne próby zbliżenia noSQL do SQL. Zespół kierowany przez Yannisa Papakonstantinou z Uniwersytetu Kalifornijskiego (San Diego) pracował nad FORWARD , implementacją SQL ++, która wkrótce może być rozwiązaniem uporczywych problemów, takich jak ten opublikowany tutaj.
Na bardziej praktycznym poziomie, wydanie Couchbase 4.0 oznaczało, że po raz pierwszy możesz wykonywać natywne JOIN w NoSQL. Używają własnego N1QL. Oto przykład
JOIN
z ich samouczków :N1QL pozwala na większość, jeśli nie wszystkie, operacje SQL, w tym agregację, filtrowanie itp.
NIE-TAK NOWE ROZWIĄZANIE HYBRYDOWE
Jeśli MongoDB jest nadal jedyną opcją, to chciałbym wrócić do mojego punktu, że aplikacja powinna mieć pierwszeństwo przed strukturą danych. Żadna z odpowiedzi nie wspomina o osadzaniu hybrydowym, w którym większość danych, o które chodzi, jest osadzana w dokumencie / obiekcie, a odniesienia są zachowywane dla mniejszości przypadków.
Przykład: czy informacje (inne niż nazwa roli) mogą czekać? czy ładowanie aplikacji może być szybsze, jeśli nie żąda się niczego, czego użytkownik jeszcze nie potrzebuje?
Może tak być w przypadku, gdy użytkownik loguje się i musi zobaczyć wszystkie opcje dla wszystkich ról, do których należy. Jednak użytkownik jest „Inżynierem” i opcje tej roli są rzadko używane. Oznacza to, że aplikacja musi tylko wyświetlać opcje dla inżyniera na wypadek, gdyby chciał je kliknąć.
Można to osiągnąć za pomocą dokumentu, który informuje aplikację na początku (1), do jakich ról należy użytkownik i (2) gdzie uzyskać informacje o zdarzeniu związanym z określoną rolą.
Lub, jeszcze lepiej, zindeksuj pole role.name w kolekcji ról i może nie być konieczne osadzanie ObjectID ().
Inny przykład: czy informacje o WSZYSTKICH żądanych rolach są CAŁKOWITE?
Może się również zdarzyć, że użytkownik loguje się do dashboardu i 90% czasu wykonuje zadania związane z rolą „Inżyniera”. Osadzanie hybrydowe można wykonać dla tej konkretnej roli w całości i zachować odniesienia tylko do reszty.
Brak schematów jest nie tylko cechą NoSQL, ale w tym przypadku może być zaletą. Zagnieżdżanie różnych typów obiektów we właściwości „Role” obiektu użytkownika jest całkowicie prawidłowe.
źródło
w przypadku, gdy pracownik i firma są podmiotem-obiektem, spróbuj zastosować następujący schemat:
źródło