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