在Slick 2.1中,我需要执行查询/ map
操作,如果它包含某个非空值,我将可空字段转换为None。不确定它是否重要,但在我的情况下,所讨论的列类型是映射列类型。这是一个代码片段,试图说明我正在尝试做什么。它不会编译,因为编译器不喜欢None
。
case class Record(field1: Int, field2: Int, field3: MyEnum)
sealed trait MyEnum
val MyValue: MyEnum = new MyEnum { }
// table is a TableQuery[Record]
table.map { r => (
r.field1,
r.field2,
Case If (r.field3 === MyValue) Then MyValue Else None // compile error on 'None'
)
}
错误是这样的:
type mismatch; found : None.type required: scala.slick.lifted.Column[MyEnum]
实际上,我想这样做的原因是我想要执行groupBy
,其中我计算field3
包含给定值的记录数。我无法使更复杂的groupBy
表达式工作,所以我退回到这个更简单的例子,我仍然无法工作。如果有更直接的方式向我展示groupBy
表达式,那也没关系。谢谢!
更新
我尝试了@cvogt建议的代码,但这会产生编译错误。这是一个SSCCE,万一有人能在这里发现我做错了什么。编译失败,“value?不是Int的成员”:
import scala.slick.jdbc.JdbcBackend.Database
import scala.slick.driver.H2Driver
object ExpMain extends App {
val dbName = "mydb"
val db = Database.forURL(s"jdbc:h2:mem:${dbName};DB_CLOSE_DELAY=-1", driver = "org.h2.Driver")
val driver = H2Driver
import driver.simple._
class Exp(tag: Tag) extends Table[(Int, Option[Int])](tag, "EXP") {
def id = column[Int]("ID", O.PrimaryKey)
def value = column[Option[Int]]("VALUE")
def * = (id, value)
}
val exp = TableQuery[Exp]
db withSession { implicit session =>
exp.ddl.create
exp += (1, (Some(1)))
exp += (2, None)
exp += (3, (Some(4)))
exp.map { record =>
Case If (record.value === 1) Then 1.? Else None // this will NOT compile
//Case If (record.value === 1) Then Some(1) Else None // this will NOT compile
//Case If (record.value === 1) Then 1 Else 0 // this will compile
}.foreach {
println
}
}
}
答案 0 :(得分:2)
我需要执行查询/映射操作,如果它包含某个非空值,我将可空字段转换为None
鉴于您在更新中拥有的示例数据,并假装1
是您关注的“特定”值,我相信这是您期望的输出:
None, None, Some(4)
(对于ID为1,2和3的行)
如果我正确理解了问题,这就是你需要的......?
val q: Query[Column[Option[Int]], Option[Int], Seq] = exp.map { record =>
Case If (record.value === 1) Then (None: Option[Int]) Else (record.value)
}
......相当于:
select (case when ("VALUE" = 1) then null else "VALUE" end) from "EXP"
答案 1 :(得分:1)
您需要将MyValue包装在一个Option中,以便条件的两个结果都是选项。在Slick 2.1中你使用。?操作员。在Slick 3.0中,它可能是Rep.Some(...)。
尝试
Case If (r.field3 === MyValue) Then MyValue.? Else None
或
Case If (r.field3 === MyValue) Then MyValue.? Else (None: Option[MyEnum])