计算 select 输出中的派生列 - Scala Slick 3.2.3
Calculate a derived column in the select output - Scala Slick 3.2.3
我正在尝试编写一些 REST API 以使用 Scala Slick 3.2.3 获取数据。有没有办法计算派生列并将其包含在返回的输出中?
我的模特:
case class Task(id: Option[TaskId], title: String, dueOn: String, status: String, createdAt: String, updatedAt: String)
Table class:
class TasksTable(tag: Tag) extends Table[Task](tag, _tableName = "TASKS") {
def id: Rep[TaskId] = column[TaskId]("ID", O.PrimaryKey, O.AutoInc)
def title: Rep[String] = column[String]("TITLE")
def dueOn: Rep[String] = column[String]("DUE_ON")
def status: Rep[String] = column[String]("STATUS")
def createdAt: Rep[String] = column[String]("CREATED_AT")
def updatedAt: Rep[String] = column[String]("UPDATED_AT")
def * = (id.?, title, dueOn, status, createdAt, updatedAt) <> ((Task.apply _).tupled, Task.unapply)
}
DAO:
object TasksDao extends BaseDao {
def findAll: Future[Seq[Task]] = tasksTable.result
}
我想在响应 json 中添加一个名为 timeline
的列,其值为 "overdue"、"today"、"tomorrow"、"upcoming"等根据dueOn
值计算。
我尝试搜索但找不到任何帮助。对示例或任何指针的任何帮助将不胜感激。谢谢!
首先,我将从为时间轴定义枚举模型开始:
object Timelines extends Enumeration {
type Timeline = Value
val Overdue: Timeline = Value("overdue")
val Today: Timeline = Value("today")
val Tomorrow: Timeline = Value("tomorrow")
val Upcoming: Timeline = Value("upcoming")
}
然后我将 dueOne
列类型从普通 String
修改为 LocalDate
- 这在 DAO 级别上更容易完成,因此 Slick 将为我们处理解析错误。
因此,需要为 LocalDate
定义自定义类型(有关详细信息,请参阅:http://scala-slick.org/doc/3.0.0/userdefined.html#using-custom-scalar-types-in-queries)。
// Define mapping between String and LocalDate
private val defaultDateFormat: DateTimeFormatter = DateTimeFormatter.ISO_DATE // replace it with formatter you use for a date
def stringDateColumnType(format: DateTimeFormatter): BaseColumnType[LocalDate] = {
MappedColumnType.base[LocalDate, String](_.format(format), LocalDate.parse(_, format))
}
implicit val defaultStringDateColumnType: BaseColumnType[LocalDate] = stringDateColumnType(defaultDateFormat)
private val defaultDateFormat: DateTimeFormatter = DateTimeFormatter.ISO_DATE // replace it with formatter you use for a date
// Change `dueOn` from String to LocalDate
case class Task(id: Option[TaskId], title: String, dueOn: LocalDate, status: String, createdAt: String, updatedAt: String)
class TasksTable(tag: Tag) extends Table[Task](tag, _tableName = "TASKS") {
def id: Rep[TaskId] = column[TaskId]("ID", O.PrimaryKey, O.AutoInc)
def title: Rep[String] = column[String]("TITLE")
def dueOn: Rep[LocalDate] = column[LocalDate]("DUE_ON") // Then replace column type
def status: Rep[String] = column[String]("STATUS")
def createdAt: Rep[String] = column[String]("CREATED_AT")
def updatedAt: Rep[String] = column[String]("UPDATED_AT")
def * = (id.?, title, dueOn, status, createdAt, updatedAt) <> ((Task.apply _).tupled, Task.unapply)
}
然后使用新的附加 timeline
字段定义 API 级别模型 TaskResponse
:
case class TaskResponse(id: Option[TaskId], title: String, dueOn: LocalDate, status: String, createdAt: String, updatedAt: String, timeline: Timeline)
object TaskResponse {
import Timelines._
def fromTask(task: Task): TaskResponse = {
val timeline = dueOnToTimeline(task.dueOn)
TaskResponse(task.id, task.title, task.dueOn, task.status, task.createdAt, task.updatedAt, timeline)
}
def dueOnToTimeline(dueOn: LocalDate): Timeline = {
val today = LocalDate.now()
Period.between(today, dueOn).getDays match {
case days if days < 0 => Overdue
case 0 => Today
case 1 => Tomorrow
case _ => Upcoming
}
}
}
然后你可以创建TasksService
负责转换的业务逻辑:
class TasksService(dao: TasksDao)(implicit ec: ExecutionContext) {
def findAll: Future[Seq[TaskResponse]] = {
dao.findAll.map(_.map(TaskResponse.fromTask))
}
}
希望对您有所帮助!
我正在尝试编写一些 REST API 以使用 Scala Slick 3.2.3 获取数据。有没有办法计算派生列并将其包含在返回的输出中?
我的模特:
case class Task(id: Option[TaskId], title: String, dueOn: String, status: String, createdAt: String, updatedAt: String)
Table class:
class TasksTable(tag: Tag) extends Table[Task](tag, _tableName = "TASKS") {
def id: Rep[TaskId] = column[TaskId]("ID", O.PrimaryKey, O.AutoInc)
def title: Rep[String] = column[String]("TITLE")
def dueOn: Rep[String] = column[String]("DUE_ON")
def status: Rep[String] = column[String]("STATUS")
def createdAt: Rep[String] = column[String]("CREATED_AT")
def updatedAt: Rep[String] = column[String]("UPDATED_AT")
def * = (id.?, title, dueOn, status, createdAt, updatedAt) <> ((Task.apply _).tupled, Task.unapply)
}
DAO:
object TasksDao extends BaseDao {
def findAll: Future[Seq[Task]] = tasksTable.result
}
我想在响应 json 中添加一个名为 timeline
的列,其值为 "overdue"、"today"、"tomorrow"、"upcoming"等根据dueOn
值计算。
我尝试搜索但找不到任何帮助。对示例或任何指针的任何帮助将不胜感激。谢谢!
首先,我将从为时间轴定义枚举模型开始:
object Timelines extends Enumeration {
type Timeline = Value
val Overdue: Timeline = Value("overdue")
val Today: Timeline = Value("today")
val Tomorrow: Timeline = Value("tomorrow")
val Upcoming: Timeline = Value("upcoming")
}
然后我将 dueOne
列类型从普通 String
修改为 LocalDate
- 这在 DAO 级别上更容易完成,因此 Slick 将为我们处理解析错误。
因此,需要为 LocalDate
定义自定义类型(有关详细信息,请参阅:http://scala-slick.org/doc/3.0.0/userdefined.html#using-custom-scalar-types-in-queries)。
// Define mapping between String and LocalDate
private val defaultDateFormat: DateTimeFormatter = DateTimeFormatter.ISO_DATE // replace it with formatter you use for a date
def stringDateColumnType(format: DateTimeFormatter): BaseColumnType[LocalDate] = {
MappedColumnType.base[LocalDate, String](_.format(format), LocalDate.parse(_, format))
}
implicit val defaultStringDateColumnType: BaseColumnType[LocalDate] = stringDateColumnType(defaultDateFormat)
private val defaultDateFormat: DateTimeFormatter = DateTimeFormatter.ISO_DATE // replace it with formatter you use for a date
// Change `dueOn` from String to LocalDate
case class Task(id: Option[TaskId], title: String, dueOn: LocalDate, status: String, createdAt: String, updatedAt: String)
class TasksTable(tag: Tag) extends Table[Task](tag, _tableName = "TASKS") {
def id: Rep[TaskId] = column[TaskId]("ID", O.PrimaryKey, O.AutoInc)
def title: Rep[String] = column[String]("TITLE")
def dueOn: Rep[LocalDate] = column[LocalDate]("DUE_ON") // Then replace column type
def status: Rep[String] = column[String]("STATUS")
def createdAt: Rep[String] = column[String]("CREATED_AT")
def updatedAt: Rep[String] = column[String]("UPDATED_AT")
def * = (id.?, title, dueOn, status, createdAt, updatedAt) <> ((Task.apply _).tupled, Task.unapply)
}
然后使用新的附加 timeline
字段定义 API 级别模型 TaskResponse
:
case class TaskResponse(id: Option[TaskId], title: String, dueOn: LocalDate, status: String, createdAt: String, updatedAt: String, timeline: Timeline)
object TaskResponse {
import Timelines._
def fromTask(task: Task): TaskResponse = {
val timeline = dueOnToTimeline(task.dueOn)
TaskResponse(task.id, task.title, task.dueOn, task.status, task.createdAt, task.updatedAt, timeline)
}
def dueOnToTimeline(dueOn: LocalDate): Timeline = {
val today = LocalDate.now()
Period.between(today, dueOn).getDays match {
case days if days < 0 => Overdue
case 0 => Today
case 1 => Tomorrow
case _ => Upcoming
}
}
}
然后你可以创建TasksService
负责转换的业务逻辑:
class TasksService(dao: TasksDao)(implicit ec: ExecutionContext) {
def findAll: Future[Seq[TaskResponse]] = {
dao.findAll.map(_.map(TaskResponse.fromTask))
}
}
希望对您有所帮助!