Обработка списочных типов с помощью Esqueleto

144

У меня есть типы данных, определенные как:

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запросов? Есть ли другие варианты?

без мужчин
источник
2
Вы смотрели Data.List.groupBy?
cdk
@ CDK: Да, это то, что я шел с. Это становится удивительно волосатым, хотя.
номен

Ответы:

2

Esqueleto НЕ предназначен для обработки списка подсписков (многомерного списка) прямо из коробки! Data.List.groupByтот «cdk», который вам посоветовал, может группировать только сам список, но не то, что вы просили.

Для вашего случая я настоятельно советую вам использовать классические SQL-запросы. Вы можете запускать n + 1 запросов, но делать это, только если это редкая и не часто используемая функция, которая, например, подготавливает кэшированные данные (основываясь на именах ваших переменных, я полагаю, что они могут быть не слишком интенсивными и их стоит попробовать). Для интенсивного использования вы должны рассмотреть возможность использования классического SQL без каких-либо сомнений.

Если вы перейдете на https://github.com/prowdsponsor/esqueleto, вы обнаружите, что:

Не все функции SQL доступны, но большинство из них могут быть легко добавлены (особенно функции).

так что вы можете попробовать запросить новую функцию. Удачи!

Kainax
источник
У вас есть ссылка на источник по этому вопросу? Я буду рад назначить вознаграждение, если кто-то может подтвердить, что это правильный ответ, или вы можете предоставить какую-то документацию.
Tech Savant
@ NotoriousPet0 Если вы зайдете на сайт haskell, вы найдете полный список примеров и вариантов использования, и ни один из них не использует многомерные списки, даже «внутреннее соединение». Если вы будете искать «group by» там, вы обнаружите, что его можно использовать для включения нескольких столбцов в кортеж или сортировки с помощью дополнительной функции агрегирования. Там также говорится, что разработчики пытаются сделать Esqueleto максимально гибким для поддержки любого запроса, поэтому вы можете запросить дополнительное расширение здесь .
Kainax