Mongo część query

0

Cześć, czy stosująć Mongo i chcąc używać wzoraca CQRS mamy jakieś sprawdzone sposoby na część query ? Bo tu raczej nie ma joinów czy widoków jak w relacyjnej DB.

Chciałbym oddzielić obiekty domenowe z logiką od projekcji zwracanych na potrzeby klientów.

Chyba, że muszę ręcznie to wszystko pisać i joinować w kodzie ?

3

Z "definicji" masz 2 modele - do odczytu (zdenormalizowany!) i zapisu. Czyli możesz mieć 2 oddzielne kolekcje na Mongo. Pomyśl o tym w ten sposób, że być może przy odczycie kiedyś podmienisz Mongo na Elastica.

Ew. masz coś takiego: https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/ ale to się mija z celem.

0

@Charles_Ray:

Ok, ale do takiej architektury potrzebuję emitować eventy i aktualizować te kolekcje widokowe przy każdym zapisie prawda ? Czyli jakiś rabbit np.

Z SQL mógłbym po prostu tworzyć widoki w bazie albo jakimiś @ManyToOne to ogarnąc po stronie kodu.

3
  1. Nie musisz emitować żadnych eventów - możesz po prostu aktualizujesz 2 dokumenty przy zapisie. Tracisz oczywiście gwarancję spójności danych. Oczywiście to się słabo skaluje w kodzie, więc jakiś pattern typu observer tutaj można zastosować i w ten sposób wpinać kolejne projekcje (modele do odczytu pod różne use casy). Ewolucją na poziomie architektury jest dostawienie kolejki i wejście w asynchroniczność. Spora cena, nie zawsze warto.
  2. Nie. @ManyToOne jest joinem na poziomie SQL, a nie joinem client-side. Na start tworzenie widoków (a potem ich materializowanie) wydaje mi się dobrym pomysłem.

Polecam:

0

@Charles_Ray:

A jeśli mam Mongo i nie mam transakcji i wywali mi się zapis tego modelu widokowego to wjeżdża spora niespójność. Jak to się potem naprawia ? Jakoś za pomocą tego obserwatora, który muszę zaimplementować ?

1

Tak jak @Charles_Ray wspomniał, możesz po prostu zapisywać zdenormalizowany model na potrzeby widoku. Wtedy przechowujesz to jako jeden duży dokument, bez konieczność wyciągania dodatkowych dokumentów. Tak naprawdę nie ma tutaj znaczenia czy mowa o MongoDB czy jakiejkolwiek innej bazie. Poza tym jeśli chcesz zapisywać model command i query jednocześnie, z zachowaniem transakcyjności to warto rozejrzeć się za bazą która to w pełni wspiera jeśli masz możliwość. Uważaj na transakcje w MongoDB.

0

@Aventus:
Ok, odpowiada mi to z zapisywaniem modelu query od razu, aby nie wprowadzać asynchroniczności.

Zastanawiam się tylko jak ogarnąć case kiedy walnie mi zapis modelu query po tym jak zapis command się powiódł.

0

A musisz korzystać z MongoDB? Bo tak jak mówiłem brzmi to jakbyś potrzebował transakcyjności, a wtedy najlepiej użyć technologii która to ma (i działa). W przeciwnym razie będziesz musiał sam spróbować jakoś ogarnąć taką "transakcję", ale w tej kwestii nic nie jestem w stanie doradzić.

Jeśli piszesz coś od zera i nie masz jakichś ograniczeń to zastanów się może nad inną technologią. Od siebie mogę polecić RavenDB.

0

No właśnie ! :)

I to jest case tego tematu. Czy da się pożenić Mongo i CQRS w jakiś przyjazny sposób.

Bo SQLem to nie sztuka no.

1

Z tego co widzę to teoretycznie do tego masz multi-document transactions w MongoDB, ale polecam przeczytać podlinkowany wcześniej artykuł.

1

Chwilunia, ustalmy po co Ci wgl ten CQRS jak chcesz mieć absolutna spójność :) w rozproszonym systemie widok może być oddzielna usługa feedowaną eventami i wtedy musisz liczyć się z tym, że czasem trzeba puścić retransmisje eventów, żeby widok nadrobił.

1

@Charles_Ray: dobrze mówisz, tylko że słowo klucz to spójność. W eventual consistency ta spójność następuje... tylko że ostatecznie/końcowo. OP martwi się (całkiem słusznie) że spójność straci całkowicie, bo w wyniku błędu zapisze coś do command ale nie query side.

1

No jasne, trzeba to ograć. To zależy od stopnia (nie)spójności, na jaki może pozwolić sobie aplikacja, a to z kolei jest związane z ruchem jaki ma uciągnąć. Zakładam, że brak spójności nie jest akceptowalne :)

Z kontekstu wnioskuje, że najlepszym wyjściem byłoby to zrobić na widokach w SQL :) wtedy przynajmniej na poziomie kodu jest ładnie, mówił o tym m.in. JNabrdalik na jednym z talków

0

@Charles_Ray: A jak po prostu muszę mieć bazę dokumentową, a nie relacyjną ?

To chyba po prostu zostaje w części query pobrać te encje domenowe, zrobić jakieś metody toDto() w nich i zmergować to w kodzie biznesowym w obiekt query ?

Nie mam żadnego rozproszonego systemu, chcę to zrobić jak najłatwiej bez kombinowania, ale po prostu zauważyłem, że sporo kodu w części query, która mi merguje te obiekty domowe w widok (czyli to co opisałem wyżej dla rozwiązania z mongo).

1

No to albo nie robiłbym CQRS, albo skorzystałbym z aggregation framework, tam można pisać zapytania po wielu kolekcjach. Mały w tym sens, ale ładniejszy podział w kodzie oraz wpis do CV będzie :)

0

Nie potrzebuję tu nic do cv :D A jak to bez CQRS ?

Po prostu tak jak piszę pobrać kolekcje obiektów domenowych, zmapować do dto i pomergować ?

1

A może użycie widoków Mongo w tym przypadku będzie dobrym wyjściem?
Widoki mongo tworzone są z istniejących kolekcji więc teoretycznie odczyty zawsze będą miały aktualny stan. Pod maską widoków w mongo kryje się zwyczajna agregacja.

0

Tak na marginesie da się robić ala sql joiny w mongo, właśnie używać agregatów. https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/.
Miałem przypadek w projekcie gdzie przy użyciu mongoTemplate (z spring data) stworzyliśmy zapytanie w którym pobieraliśmy dane z dwóch róznych kolekcji + inne operacje. Później wynik takiego query od razu był mapowany do zwykłego DTO.

1 użytkowników online, w tym zalogowanych: 0, gości: 1