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 by
no SQL? Como dobrar linhas para terminar com uma lista de listas de pessoas?
Tenho a impressão de que esqueleto
nã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+1
consultas? Existem outras opções?
Data.List.groupBy
?Respostas:
Esqueleto NÃO pretende lidar com a lista de sublistas (lista multidimensional) fora da caixa ainda!
Data.List.groupBy
aquele '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:
para tentar solicitar um novo recurso. Boa sorte!
fonte