用 Esqueleto 处理列表类型

我将数据类型定义为:

data ComitteeView = CommitteeView { committeeId :: CommitteeId
, committeeMembers :: [Person]
}


data CommitteesView = CommitteesView { committeeView :: [CommitteeView] }

现在,就目前情况来看,我有一个持久模型定义为:

Person
name  Text


Committee
name  Text


CommitteePerson
personId    PersonId
committeeId CommitteeId

我可以很容易地创建一个查询,用 Esqueleto 填充一个 Committee View:

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

现在,考虑填充 CommitteesView的问题。原则上,我们可以通过在上面的查询中运行子查询来获得足够的数据。好吧,有道理。现在我如何在 SQL 中使用像 group by那样的“ group by Haskell-list”?如何折叠行以便最终得到一个人员列表?

我得到的印象是 esqueleto不能像这样处理这种情况(也就是说,它没有一个可以做到这一点的组合子)。我的底层数据库显然不支持将 Haskell 列表作为一个列。但是,我肯定不是唯一一个面对这个问题的人。什么是有效的战略?将 n 列表折叠成 n 列表?或者运行 n+1查询?还有别的选择吗?

2709 次浏览

Esqueleto 是 没有的意思是处理子列表(多维列表)开箱即用!“ cdk”建议你的 Data.List.groupBy只能列出它自己,而不能列出你要求的内容。

对于您的情况,我坚持建议您使用经典的 SQL 查询。您可以运行 n + 1查询,但是只有当它是罕见且不常用的函数时才这样做,例如准备缓存数据(基于您的变量名称,我认为它可能使用不多,值得一试)。对于大量使用,您应该毫无疑问地考虑使用经典 SQL。

如果你去 https://github.com/prowdsponsor/esqueleto,你会发现:

并非所有 SQL 特性都可用,但大多数特性都很容易实现 添加的(特别是函数)。

所以你可以尝试要求一个新的功能。祝你好运!