У меня есть типы данных, определенные как:
data ComitteeView = CommitteeView { committeeId :: CommitteeId
, committeeMembers :: [Person]
}
data CommitteesView = CommitteesView { committeeView :: [CommitteeView] }
Теперь у меня есть постоянная модель, определенная как:
Person
name Text
Committee
name Text
CommitteePerson
personId PersonId
committeeId CommitteeId
Я могу довольно легко создать запрос для заполнения CommitteeView, используя Esqueleto. Было бы что-то вроде этого:
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
Теперь рассмотрим проблему заселения CommitteesView
. В принципе, мы получаем достаточно данных для заполнения, выполнив подзапрос в приведенном выше запросе. Хорошо, достаточно справедливо. Теперь, как я могу использовать «group by Haskell-list», как group by
в SQL? Как я могу сложить строки, чтобы я мог получить список списков людей?
У esqueleto
меня складывается впечатление, что я не могу справиться со случаем как таковым (то есть у него нет комбинатора, который бы это делал). И моя базовая база данных, очевидно, не поддерживает списки Haskell в виде столбца. Но, конечно, я не могу быть единственным человеком, который сталкивается с этой проблемой. Что такое эффективная стратегия? Сложить n-список списков в n-список? Или выполнение n+1
запросов? Есть ли другие варианты?
Data.List.groupBy
?Ответы:
Esqueleto НЕ предназначен для обработки списка подсписков (многомерного списка) прямо из коробки!
Data.List.groupBy
тот «cdk», который вам посоветовал, может группировать только сам список, но не то, что вы просили.Для вашего случая я настоятельно советую вам использовать классические SQL-запросы. Вы можете запускать n + 1 запросов, но делать это, только если это редкая и не часто используемая функция, которая, например, подготавливает кэшированные данные (основываясь на именах ваших переменных, я полагаю, что они могут быть не слишком интенсивными и их стоит попробовать). Для интенсивного использования вы должны рассмотреть возможность использования классического SQL без каких-либо сомнений.
Если вы перейдете на https://github.com/prowdsponsor/esqueleto, вы обнаружите, что:
так что вы можете попробовать запросить новую функцию. Удачи!
источник