Tengo tipos de datos definidos como:
data ComitteeView = CommitteeView { committeeId :: CommitteeId
, committeeMembers :: [Person]
}
data CommitteesView = CommitteesView { committeeView :: [CommitteeView] }
Ahora, tal como está, tengo un modelo Persistente definido como:
Person
name Text
Committee
name Text
CommitteePerson
personId PersonId
committeeId CommitteeId
Puedo crear una consulta con bastante facilidad para llenar un CommitteeView, usando Esqueleto. Sería algo así:
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
Ahora, considere el problema de poblar CommitteesView
. En principio, obtenemos suficientes datos para completar ejecutando subconsultas en la consulta anterior. De acuerdo, bastante justo. Ahora, ¿cómo puedo usar "group by Haskell-list" como group by
en SQL? ¿Cómo puedo plegar filas para que pueda terminar con una lista de listas de personas?
Me da la impresión de que esqueleto
no puede manejar el caso como tal (es decir, no tiene un combinador que lo haga). Y mi base de datos subyacente obviamente no admite las listas de Haskell como una columna. Pero, seguramente, no puedo ser la única persona que enfrenta este problema. ¿Qué es una estrategia efectiva? ¿Plegar una lista n de listas en una lista n? O ejecutando n+1
consultas? ¿Hay más opciones?
Data.List.groupBy
?Respuestas:
¡Esqueleto NO está destinado a manejar listas de sublistas (lista multidimensional) fuera de la caja todavía!
Data.List.groupBy
que 'cdk' le aconsejó que solo pueda agruparse, pero no lo que estaba pidiendo.Para su caso, le aconsejaría insistentemente que use consultas clásicas de SQL. Puede ejecutar consultas n + 1, pero haga eso solo si es una función poco frecuente y no utilizable, que por ejemplo prepara datos almacenados en caché (en función de los nombres de sus variables, supongo que puede que no se use mucho y valga la pena intentarlo). Para un uso intensivo, debe considerar usar SQL clásico sin ninguna duda.
Si va a https://github.com/prowdsponsor/esqueleto encontrará que:
para que pueda intentar solicitar una nueva función. ¡Buena suerte!
fuente