Manipulação de tipos de lista com Esqueleto

144

Eu tenho tipos de dados definidos como:

data ComitteeView = CommitteeView { committeeId :: CommitteeId
                                  , committeeMembers :: [Person] 
                                  }

data CommitteesView = CommitteesView { committeeView :: [CommitteeView] }

Agora, como está, eu tenho um modelo persistente definido como:

Person
  name  Text

Committee
  name  Text

CommitteePerson
  personId    PersonId
  committeeId CommitteeId

Posso facilmente criar uma consulta para preencher um CommitteeView, usando Esqueleto. Seria algo como isto:

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

Agora, considere o problema de preencher CommitteesView. Em princípio, obtemos dados suficientes para preencher executando a subconsulta na consulta acima. Ok, é justo. Agora, como posso usar "group by Haskell-list" como group byno SQL? Como dobrar linhas para terminar com uma lista de listas de pessoas?

Tenho a impressão de que esqueletonão posso lidar com o caso como tal (ou seja, ele não tem um combinador que o faria). E meu banco de dados subjacente obviamente não suporta listas Haskell como uma coluna. Mas, certamente, não posso ser a única pessoa a enfrentar esse problema. O que é uma estratégia eficaz? Dobrar uma lista n de listas em uma lista n? Ou executando n+1consultas? Existem outras opções?

nomenclatura
fonte
2
Você já olhou Data.List.groupBy?
cdk
@cdk: Sim, é com isso que eu ando. Fica surpreendentemente peludo, no entanto.
N

Respostas:

2

Esqueleto NÃO pretende lidar com a lista de sublistas (lista multidimensional) fora da caixa ainda! Data.List.groupByaquele 'cdk' aconselhado a você pode agrupar apenas a lista em si, mas não o que você estava pedindo.

Para o seu caso, recomendo insistentemente que você use consultas SQL clássicas. Você pode executar n + 1 consultas, mas faça isso apenas se for uma função rara e nem sempre utilizável, que, por exemplo, prepara dados em cache (com base nos nomes de suas variáveis, suponho que talvez não seja muito usado e vale a pena tentar). Para uso pesado, considere usar o SQL clássico sem qualquer dúvida.

Se você for para https://github.com/prowdsponsor/esqueleto, verá que:

Nem todos os recursos do SQL estão disponíveis, mas a maioria deles pode ser facilmente adicionada (especialmente funções).

para tentar solicitar um novo recurso. Boa sorte!

Kainax
fonte
Você tem um link para uma fonte sobre isso? Ficarei feliz em conceder a recompensa se alguém puder verificar se esta é a resposta correta ou se você pode fornecer algum tipo de documentação.
Tech Savant
@ NotoriousPet0 Se você acessar o site da haskell , encontrará uma lista completa de exemplos e casos de uso, e nenhum deles usa listas multidimensionais, até mesmo "junção interna". Se você procurar um "agrupar por" lá, descobrirá que ele pode ser usado para incluir várias colunas em uma tupla ou classificar por função agregada adicional. Também se diz lá que os desenvolvedores tentam tornar o Esqueleto o mais flexível possível para suportar qualquer consulta, para que você possa solicitar uma extensão adicional aqui .
Kainax 12/07/2015