我有一个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>
答案 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
。