使用 Esqueleto 处理列表类型

Posted

技术标签:

【中文标题】使用 Esqueleto 处理列表类型【英文标题】:Handling List-types with Esqueleto 【发布时间】:2014-07-08 04:53:42 【问题描述】:

我的数据类型定义为:

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

data CommitteesView = CommitteesView  committeeView :: [CommitteeView] 

现在,就目前而言,我有一个 Persistent 模型定义为:

Person
  name  Text

Committee
  name  Text

CommitteePerson
  personId    PersonId
  committeeId CommitteeId

使用 Esqueleto,我可以很容易地创建一个查询来填充委员会视图。它会是这样的:

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 这样的“按 Haskell-list 分组”?如何折叠行以便最终得到人员列表?

我的印象是esqueleto 无法处理这种情况(即,它没有可以做到这一点的组合器)。而且我的底层数据库显然不支持将 Haskell 列表作为列。但是,当然,我不能是唯一一个面对这个问题的人。什么是有效的策略?将列表的n列表折叠成n列表?或者运行n+1 查询?还有其他选择吗?

【问题讨论】:

你看过Data.List.groupBy吗? @cdk:是的,这就是我一直在做的。不过,它会令人惊讶地多毛。 【参考方案1】:

Esqueleto 旨在处理开箱即用的子列表(多维列表)! Data.List.groupBy 'cdk' 建议您只能对列表本身进行分组,但不能对您的要求进行分组。

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

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

并非所有 SQL 功能都可用,但大多数功能都可以轻松使用 添加(尤其是函数)。

所以您可以尝试请求新功能。祝你好运!

【讨论】:

你有这个来源的链接吗?如果有人可以验证这是正确的答案,或者您可以提供某种文件,我将很乐意奖励赏金。 @NotoriousPet0 如果你继续haskell website,你会发现完整的示例和用例列表,它们都没有使用多维列表,甚至“内连接”。如果您在那里搜索“分组依据”,您会发现它可用于将多个列包含在一个元组中或通过附加聚合函数进行排序。那里还说开发人员试图使 Esqueleto 尽可能灵活地支持任何查询,因此您可以要求额外的扩展 here。

以上是关于使用 Esqueleto 处理列表类型的主要内容,如果未能解决你的问题,请参考以下文章

SQL:List-Field 包含子列表

在 Esqueleto 中获取聚合函数的结果

Haskell Persistent 加入 Esqueleto

Python 特殊列表操作记录

Esqueleto:如何使用联接删除项目

C++模板参数类型列表