Manejo de tipos de listas con Esqueleto

144

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 byen 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+1consultas? ¿Hay más opciones?

no hombre
fuente
2
¿Has mirado Data.List.groupBy?
cdk
@cdk: Sí, eso es con lo que he estado yendo. Sin embargo, se vuelve sorprendentemente peludo.
nomen

Respuestas:

2

¡Esqueleto NO está destinado a manejar listas de sublistas (lista multidimensional) fuera de la caja todavía!Data.List.groupByque '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:

No todas las características de SQL están disponibles, pero la mayoría de ellas se pueden agregar fácilmente (especialmente funciones).

para que pueda intentar solicitar una nueva función. ¡Buena suerte!

Kainax
fuente
¿Tienes un enlace a una fuente sobre esto? Estaré encantado de otorgar la recompensa si alguien puede verificar que esta es la respuesta correcta o si puede proporcionar algún tipo de documentación.
Tech Savant
@ NotoriousPet0 Si visita el sitio web de haskell , encontrará una lista completa de ejemplos y casos de uso, y ninguno de ellos usa listas multidimensionales, ni siquiera "unión interna". Si busca un "grupo por" allí, encontrará que se puede usar para encerrar múltiples columnas en una tupla o clasificar por función de agregado adicional. También se dice que los desarrolladores intentan hacer que Esqueleto sea tan flexible para admitir cualquier consulta, por lo que puede solicitar una extensión adicional aquí .
Kainax