0

我有一个ConnectionIO[Option[Int]]和映射Option来产生ConnectionIO[Option[String]]一个查询,Some[Int]否则保持Nones. I was able to do this with a匹配comprehension and a`:

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]].

4

1 回答 1

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否则如果小部件查询可以为空,则它可能是可取的,但最后需要widgeta。Option[Option[String]].flatten

于 2018-02-19T01:38:08.027 回答