在没有明确匹配的情况下转换Doobie ConnectionIO [Option [Int]]

时间:2018-02-19 00:35:15

标签: scala free-monad doobie

我有一个ConnectionIO[Option[Int]]并映射Option以生成一个ConnectionIO[Option[String]],其中包含Some[Int]的查询,否则会Nones. I was able to do this with a comprehension and a } match`:

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]]。< / p>

1 个答案:

答案 0 :(得分: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]],如果小部件查询可以为null,可能是合乎需要的,但最后需要.flatten