【问题标题】:How to express Postgres arrays with Scala Slick如何用 Scala Slick 表达 Postgres 数组
【发布时间】:2017-10-19 17:43:20
【问题描述】:

我在 Postgres 9.5 中有一个具有这种结构的表:

my_table (id Integer, images_ranks image_rank[]);

image_rank 在哪里:

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

我正在努力在 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.<<)) }

正确的做法是什么?

更新

这个包裹(按照 n1r3 的回答)目前正在阻止我:

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

更新 2

仍然不确定是什么问题。我已经按照你的建议添加了代码,但它仍然抱怨:

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

所以我添加了:

implicit val myTableResult = GetResult[MyTable](r =&gt; MyTable(r.&lt;&lt;, r.&lt;&lt;))

返回:

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

这是我的配置:

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

【问题讨论】:

  • 我不确定Seq[Option[ImageRank]] 是否正确,您是想要Option[Seq[ImageRank]] 还是只是Seq[ImageRank]
  • 使用正则表达式会破坏大部分类型语言的“安全性”。所以我把它改成了至少使用“选项”。此外,这些值并不总是存在。我对 Dmitri 的“映射器”中的代码进行了一些调整。
  • 对。但是可以假设数据库是一个受信任的系统,不是吗?如果不是,就抛出一个很好的旧 RuntimeException 吗?
  • 我已删除“选项”并恢复为 Dmytro 代码,但我仍然遇到相同的错误。
  • 您是否正确导入了范围内的隐式?

标签: scala slick


【解决方案1】:

你最好使用这个优秀的库:https://github.com/tminglei/slick-pg

如果您想自己实现它,请查看源代码 (https://github.com/tminglei/slick-pg/tree/master/core/src/main/scala/com/github/tminglei/slickpg/array) 并从那里得到您想要的。

【讨论】:

  • 谢谢。在您放置的链接中,有一个 MarketFinancialProduct 作为列表元素的示例。如何用我的ImageRank 替换它?
  • @Randomize 见我的answer
【解决方案2】:

ImageRank 是什么?写出它的定义。我认为这是一个案例类

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

我猜除了 slick-pg 特定数组的映射器

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)

你应该为ImageRank 定义slick 映射器

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

文档是here

SimpleArrayJdbcTypeString 参数含义 SQL base type 所以我猜 "image_rank[]" 不会工作。

SimpleArrayJdbcType 也适用于基本类型 T 为标准且 ElemWitness[T]slick-pg 中定义的数组。由于没有ElemWitness[ImageRank],你应该使用AdvancedArrayJdbcType

【讨论】:

    猜你喜欢
    • 2021-05-20
    • 2014-02-25
    • 1970-01-01
    • 2016-02-04
    • 1970-01-01
    • 2015-10-29
    • 1970-01-01
    • 2020-08-02
    • 2020-01-11
    相关资源
    最近更新 更多