How to express Postgres arrays with Scala Slick

偶尔善良 提交于 2020-01-30 08:24:25

问题


I have a table in Postgres 9.5 with this structure:

my_table (id Integer, images_ranks image_rank[]);

where image_rank is:

CREATE TYPE image_rank AS (image_url text, thumbnail_rank integer);

I am struggling to express something like that in Slick (3.1):

case class MyTable (id: Int, imagesRanks: Seq[Option[ImageRank]])

implicit val propertyMyTableResult = GetResult(r => MyTable(r.<<, r.<<)
implicit val propertyImageRankResult = GetResult[Option[ImageRank]] { r => ImageRank(r.<<, r.<<)) }

What is the correct way to do it?

UPDATE

This wrap (following the answer from n1r3) is blocking me at the moment:

implicit val ImageRankWrapper: JdbcType[List[ImageRank]] = new SimpleArrayJdbcType[ImageRank]("image_rank[]").to(_.toList)

UPDATE 2

Still not sure what is wrong. I have added the code as you suggested, but it still complains with:

could not find implicit value for parameter rconv: slick.jdbc.GetResult[database.rows.MyTable].

So I have added:

implicit val myTableResult = GetResult[MyTable](r => MyTable(r.<<, r.<<))

which returns:

diverging implicit expansion for type slick.jdbc.GetResult[T1]
starting with object GetStringOption in object GetResult
         r.<<, r.<<))

This is my configuration:

import com.github.tminglei.slickpg._
import database.rows.ImageRank

trait CustomPostgresProfile extends ExPostgresProfile
  with PgArraySupport
  with PgPlayJsonSupport
  with PgPostGISSupport
  with PgEnumSupport
  with PgDate2Support {

  // Use PostgreSQL JSONB support
  def pgjson = "jsonb"

  override val api = MyAPI
  object MyAPI extends API
    with ArrayImplicits
    with JsonImplicits
    with PostGISImplicits
    with DateTimeImplicits {
    implicit val imageRankListTypeMapper =
      new AdvancedArrayJdbcType[ImageRank]("image_rank",
        str => utils.SimpleArrayUtils.fromString[ImageRank](s => {
          val ImageRankRegex = "ImageRank\\((.*),(\\d+)\\)".r
          s match {
            case ImageRankRegex(imageUrl, thumbnailRank) =>
              ImageRank(imageUrl, thumbnailRank.toInt)
            case _ =>
              println(s"$s is not ImageRank")
              ImageRank("", 0)
          }
        })(str).orNull,
        imageRanks => utils.SimpleArrayUtils.mkString[ImageRank](_.toString)(imageRanks)
      ).to(_.toList)
  }
}

object CustomPostgresProfile extends CustomPostgresProfile


abstract class DatabaseProfile(val provider: DatabaseConfigProvider) {
  val config = provider.get[CustomPostgresProfile]
  val profile = config.profile
  val db = config.db
}

trait PropertyDataDatabase {
    self: DatabaseProfile =>
    .....

回答1:


The best would be for you to use this excellent library: https://github.com/tminglei/slick-pg

If you would rather implement it yourself, have a look at the source code (https://github.com/tminglei/slick-pg/tree/master/core/src/main/scala/com/github/tminglei/slickpg/array) and get what you want from there.




回答2:


What is ImageRank? Write its definition. I presume it's a case class

case class ImageRank(imageUrl: String, thumbnailRank: Int)

I guess that besides slick-pg mapper for specific array

implicit val imageRankListTypeMapper =
  new AdvancedArrayJdbcType[ImageRank]("image_rank",
    str => utils.SimpleArrayUtils.fromString[ImageRank](s => {
      val ImageRankRegex = "ImageRank\\((.*),(\\d+)\\)".r
      s match {
        case ImageRankRegex(imageUrl, thumbnailRank) =>
          ImageRank(imageUrl, thumbnailRank.toInt)
        case _ =>
          println(s"$s is not ImageRank")
          ImageRank("", 0)
      }
    })(str).orNull,
    imageRanks => utils.SimpleArrayUtils.mkString[ImageRank](_.toString)(imageRanks)
  ).to(_.toList)

you should define slick mapper for ImageRank like

case class LiftedImageRank(imageUrl: Rep[String], thumbnailRank: Rep[Int])
implicit object ImageRankShape extends CaseClassShape(LiftedImageRank.tupled, ImageRank.tupled)

Documentation is here.

SimpleArrayJdbcType has String argument meaning SQL base type so I guess "image_rank[]" won't work.

Also SimpleArrayJdbcType works with arrays whose base type T is standard and for which ElemWitness[T] is defined in slick-pg. Since there is no ElemWitness[ImageRank] you should use AdvancedArrayJdbcType.



来源:https://stackoverflow.com/questions/46808137/how-to-express-postgres-arrays-with-scala-slick

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!