J'ai des types de données définis comme:
data ComitteeView = CommitteeView { committeeId :: CommitteeId
, committeeMembers :: [Person]
}
data CommitteesView = CommitteesView { committeeView :: [CommitteeView] }
Maintenant, dans l'état actuel des choses, j'ai un modèle persistant défini comme:
Person
name Text
Committee
name Text
CommitteePerson
personId PersonId
committeeId CommitteeId
Je peux assez facilement créer une requête pour remplir un CommitteeView, en utilisant Esqueleto. Cela donnerait quelque chose comme ceci:
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
Maintenant, considérons le problème du peuplement CommitteesView
. En principe, nous obtenons suffisamment de données à remplir en exécutant une sous-requête dans la requête ci-dessus. D'accord, très bien. Maintenant, comment puis-je utiliser "group by Haskell-list" comme group by
dans SQL? Comment puis-je plier des lignes pour obtenir une liste de listes de personnes?
J'ai l'impression que je esqueleto
ne peux pas gérer le cas en tant que tel (c'est-à-dire qu'il n'a pas de combinateur qui le ferait). Et ma base de données sous-jacente ne prend évidemment pas en charge les listes Haskell en tant que colonne. Mais, sûrement, je ne peux pas être la seule personne à faire face à ce problème. Qu'est-ce qu'une stratégie efficace? Plier une n-liste de listes en une n-liste? Ou exécuter des n+1
requêtes? Il y a-t-il des alternatives?
Data.List.groupBy
?Réponses:
Esqueleto n'est PAS destiné à gérer la liste des sous-listes (liste multidimensionnelle) prête à l'emploi!
Data.List.groupBy
ce 'cdk' qui vous a été conseillé ne peut se grouper que lui-même, mais pas ce que vous demandiez.Pour votre cas, je vous conseillerais avec insistance d'utiliser une requête SQL classique. Vous pouvez exécuter des requêtes n + 1, mais ne le faites que si c'est une fonction rare et pas souvent utilisable, qui prépare par exemple des données en cache (en fonction des noms de vos variables, je suppose que cela peut ne pas être lourdement utilisé et cela vaut la peine d'essayer). Pour un usage intensif, vous devriez envisager d'utiliser le SQL classique sans aucun doute.
Si vous allez sur https://github.com/prowdsponsor/esqueleto, vous trouverez que:
afin que vous puissiez essayer de demander une nouvelle fonctionnalité. Bonne chance!
la source