Преобразование Doobie ConnectionIO[Option[Int]] без явного соответствия

У меня есть ConnectionIO[Option[Int]] и карта над Option производить ConnectionIO[Option[String]] с запросом Some[Int] в противном случае сохраните Nones. I was able to do this with aзаcomprehension 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]],

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 в конце.

Другие вопросы по тегам