Mam typy danych zdefiniowane jako:
data ComitteeView = CommitteeView { committeeId :: CommitteeId
, committeeMembers :: [Person]
}
data CommitteesView = CommitteesView { committeeView :: [CommitteeView] }
Teraz, w obecnej formie, mam model Trwały zdefiniowany jako:
Person
name Text
Committee
name Text
CommitteePerson
personId PersonId
committeeId CommitteeId
Mogę łatwo utworzyć zapytanie w celu wypełnienia CommitteeView, używając Esqueleto. To wyglądałoby mniej więcej tak:
getCommitteeView cid =
CommitteeView <$> runDB $
select $
from (person `InnerJoin` pxc `InnerJoin` committee) -> do
on (committee ^. CommitteeId ==. pxc ^. CommitteePersonCommitteeId)
on (person ^. PersonId ==. pxc ^. CommitteePersonPersonId)
where_ (committee ^. CommitteePersonCommitteeId ==. val cid)
return person
Rozważmy teraz problem zaludnienia CommitteesView
. Zasadniczo uzyskujemy wystarczającą ilość danych do wypełnienia, uruchamiając podzapytanie w powyższym zapytaniu. Dobra, w porządku. Jak mogę teraz używać „group by Haskell-list”, tak jak group by
w SQL? Jak mogę złożyć wiersze, aby otrzymać listę osób?
Mam wrażenie, że esqueleto
nie poradzi sobie ze sprawą jako taką (tj. Nie ma kombinatora, który by to zrobił). A moja bazowa baza danych oczywiście nie obsługuje list Haskella jako kolumny. Ale z pewnością nie mogę być jedyną osobą, która ma do czynienia z tym problemem. Co to jest skuteczna strategia? Złożyć n-listę list do n-listy? Albo uruchamiasz n+1
zapytania? Czy są jakieś inne opcje?
Data.List.groupBy
?Odpowiedzi:
Esqueleto NIE jest jeszcze przeznaczone do obsługi list podlist (listy wielowymiarowej) po wyjęciu z pudełka!
Data.List.groupBy
ten 'cdk' radzi ci, że możesz grupować tylko samą listę, ale nie to, o co prosiłeś.W twoim przypadku usilnie radziłbym używać klasycznych zapytań SQL. Możesz uruchamiać zapytania n + 1, ale zrób to tylko wtedy, gdy jest to rzadka i rzadko użyteczna funkcja, która na przykład przygotowuje buforowane dane (na podstawie nazw twoich zmiennych przypuszczam, że może nie być ciężko używana i warto spróbować). W przypadku intensywnego użytkowania należy bez wątpienia rozważyć użycie klasycznego SQL.
Jeśli przejdziesz do https://github.com/prowdsponsor/esqueleto , przekonasz się, że:
więc możesz spróbować poprosić o nową funkcję. Powodzenia!
źródło