You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I've found a common pattern in my programming with Esqueleto, and I'm curious if it would be possible to fold generic solution into Esqueleto. I would be willing to do this, with some guidance (I'm not sure if it's even possible, hence this rfc)
Consider a multi-to-multi Persistent model defined by:
Person
name Text
Committee
name Text
PersonCommittee
personId PersonId
committeeId CommitteeId
I might also have a "view" layer, like so:
data PersonView = PersonView { person :: Person, committees :: [Committees] }
One common task in my day-to-day work is to populate such views. A query might look something like:
\pid -> (select $ from $ \(person `InnerJoin` pxc `InnerJoin` committee) -> do
on (committee ^. CommitteId ==. pxc ^. PersonCommitteeCommitteeId)
on (pxc ^. PersonCommitteePersonId ==. person ^. PersonId)
where_ (person .^ PersonId ==. val pid))
return (person, committee)
In order to populate a PersonView, I have to "manually" perform a group by on the Haskell side -- pull the head out of the result set and fmap to aggregate the committee field into a list. It occurs to me that I will be doing this a lot, and that this could generalize to other monoidal functors.
Comments? Am I just approaching this the wrong way?
The text was updated successfully, but these errors were encountered:
I don't think you're approaching the problem the wrong way. Having to do these groupings manually is how SQL works, and esqueleto is giving you the same.
This is a non-trivial problem to solve in a general fashion. I mean, we could of course provide some function of type [(Entity a, b)] -> [(Entity a, [b])], but you'd still need to manually apply it. Also, it would become uglier if you needed to do in three or more levels. For example, if you had:
Continent
name TextCountry
name Text
at ContinentIdState
name Text
at CountryIdCity
name text
at StateIdStreet
name Text
at CityId
Another approach would be having something inside esqueleto's DSL (e.g., a GroupedInnerJoin, or some sort of function you could apply on the SqlExprs beforing returning). It may be easier to have something on this level as a user of esqueleto, but i imagine it would be harder as a developer of esqueleto.
In sum, this is an interesting problem but it would require some good thought to solve it!
PS: I know you've just posted an example, but given your PersonView type I'd expect to see outer joins in order to fetch people who aren't in any comittees, too.
Okay! I'm going to put some hours into this in a few weeks. For now, I'll do it the totally manual way. But it's time to get my product out to market. :)
I've found a common pattern in my programming with Esqueleto, and I'm curious if it would be possible to fold generic solution into Esqueleto. I would be willing to do this, with some guidance (I'm not sure if it's even possible, hence this rfc)
Consider a multi-to-multi Persistent model defined by:
I might also have a "view" layer, like so:
One common task in my day-to-day work is to populate such views. A query might look something like:
In order to populate a PersonView, I have to "manually" perform a group by on the Haskell side -- pull the head out of the result set and fmap to aggregate the committee field into a list. It occurs to me that I will be doing this a lot, and that this could generalize to other monoidal functors.
Comments? Am I just approaching this the wrong way?
The text was updated successfully, but these errors were encountered: