【问题标题】:Transforming Doobie ConnectionIO[Option[Int]] without explicit match在没有显式匹配的情况下转换 Doobie ConnectionIO[Option[Int]]
【发布时间】:2018-02-19 00:35:14
【问题描述】:

我有一个ConnectionIO[Option[Int]] 并映射到Option 以产生一个ConnectionIO[Option[String]] 并查询Some[Int] 否则保留Nones. I was able to do this with aforcomprehension and amatch`:

def findWidgetByOwner(name: String): ConnectionIO[Option[String]] = for {
    opt <- sql"SELECT owner_id FROM owners WHERE name = $name".query[Int].option
    widget <- opt match {
        case None => None.pure[ConnectionIO]
        case Some(id) => sql"SELECT widget_name FROM widgets WHERE owner_id = $id".query[String].option
    }
} yield widget

我知道我被 ConnectionIO 容器绊倒了,但我找不到将 ConnectionIO[Option[Int]] 转换为 ConnectionIO[Option[String]] 的更简洁的映射方法。

【问题讨论】:

    标签: scala free-monad doobie


    【解决方案1】:

    使用 SQL 而不是 scala 加入会更干净:

    def findWidgetByOwner(name: String): ConnectionIO[Option[String]] = 
      sql"""
        SELECT widgets.widget_name FROM widgets WHERE owner_id = $id
        INNER JOIN owners ON widgets.owner_id = owners.owner_id
        WHERE owners.name = $name
      """.query[Int].option
    

    但是如果你想清理原始的,sequence 的一些咒语可能会起作用(未经测试):

    import cats._, cats.data._, cats.implicits._
    
    ...
    widget <- opt.map {id => 
      sql"SELECT widget_name FROM widgets WHERE owner_id = $id".query[String].unique
    }.sequence
    

    注意:您必须将query[String].option 更改为.query[String].unique,否则widget 将变为Option[Option[String]],如果小部件查询可以为空,则可能为可取,但最后需要.flatten

    【讨论】:

    • 是的,理想情况下这些事情都可以在 SQL 中解决,但问题只是使用 SQL 纯粹是为了说明组合问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-28
    • 2020-06-06
    • 2021-09-19
    • 1970-01-01
    • 2011-01-29
    相关资源
    最近更新 更多