Slick: Model Option[(col1, col2)], 所以两者都缺失或都被定义
Slick: Model Option[(col1, col2)], so that both are missing or both defined
我有 table 多个 Option[X]
列。我想模拟这样一个事实,即对于这些列,定义了 all 或缺少 all。如何做到这一点,鉴于列被定义为个人 Option[X]
?
def startDate = column[Option[LocalDate]]("start_date", O.Default(None))
def endDate = column[Option[LocalDate]]("end_date", O.Default(None))
def dateRange: Rep[Option[(LocalDate,LocalDate)]] = ??? // How to make something like this?
您可以在使用 Slick 构建投影时嵌套映射。也就是说,您可以定义 *
以包含其他 mapTo
(对于案例 class)或 <>
调用(对于自定义映射)。
使用 Int
而不是 LocalDate
的示例,
我们可以从我们想要处理的案例 class 开始:
case class Row(
name : String,
range : Option[(Int, Int)],
id : Long = 0L
)
注意 range
字段是单个值(元组),但在数据库中我们可以将其表示为两个列,分别称为 start
和 end
:
class RowTable(tag: Tag) extends Table[Row](tag, "row") {
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def name = column[String]("name")
def start = column[Option[Int]]("start")
def end = column[Option[Int]]("end")
def range = (start, end) <> (into_range, from_range)
def * = (name, range, id).mapTo[Row]
}
到 Row
的 *
投影是从我称为 range
的另一个映射构建的。
range
映射位于 start
和 end
两列上。我们提供给 <>
的是两个函数:一个函数将一对选项转换成我们想要的类型(元组的一个选项);另一个功能则相反。这些函数反映了标准库函数 tupled
和 unappy
(unapply
是一个 extractor)。
我们可以随心所欲地编写这些函数,我已经用模式匹配将它们写出来了:
def into_range(pair: (Option[Int], Option[Int])): Option[(Int, Int)] =
pair match {
case (Some(x), Some(y)) => Some((x, y))
case _ => None
}
def from_range(r: Option[(Int, Int)]): Option[(Option[Int], Option[Int])] =
r match {
case Some((x, y)) => Some((Some(x), Some(y)))
case _ => Some((None, None))
}
总之,您的 dateRange
等同于此示例中的 range
映射,但我们没有直接调用它,而是将其包含在我们的默认投影 *
中。
我有 table 多个 Option[X]
列。我想模拟这样一个事实,即对于这些列,定义了 all 或缺少 all。如何做到这一点,鉴于列被定义为个人 Option[X]
?
def startDate = column[Option[LocalDate]]("start_date", O.Default(None))
def endDate = column[Option[LocalDate]]("end_date", O.Default(None))
def dateRange: Rep[Option[(LocalDate,LocalDate)]] = ??? // How to make something like this?
您可以在使用 Slick 构建投影时嵌套映射。也就是说,您可以定义 *
以包含其他 mapTo
(对于案例 class)或 <>
调用(对于自定义映射)。
使用 Int
而不是 LocalDate
的示例,
我们可以从我们想要处理的案例 class 开始:
case class Row(
name : String,
range : Option[(Int, Int)],
id : Long = 0L
)
注意 range
字段是单个值(元组),但在数据库中我们可以将其表示为两个列,分别称为 start
和 end
:
class RowTable(tag: Tag) extends Table[Row](tag, "row") {
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def name = column[String]("name")
def start = column[Option[Int]]("start")
def end = column[Option[Int]]("end")
def range = (start, end) <> (into_range, from_range)
def * = (name, range, id).mapTo[Row]
}
到 Row
的 *
投影是从我称为 range
的另一个映射构建的。
range
映射位于 start
和 end
两列上。我们提供给 <>
的是两个函数:一个函数将一对选项转换成我们想要的类型(元组的一个选项);另一个功能则相反。这些函数反映了标准库函数 tupled
和 unappy
(unapply
是一个 extractor)。
我们可以随心所欲地编写这些函数,我已经用模式匹配将它们写出来了:
def into_range(pair: (Option[Int], Option[Int])): Option[(Int, Int)] =
pair match {
case (Some(x), Some(y)) => Some((x, y))
case _ => None
}
def from_range(r: Option[(Int, Int)]): Option[(Option[Int], Option[Int])] =
r match {
case Some((x, y)) => Some((Some(x), Some(y)))
case _ => Some((None, None))
}
总之,您的 dateRange
等同于此示例中的 range
映射,但我们没有直接调用它,而是将其包含在我们的默认投影 *
中。