Slick 3 return custom case class from query

删除回忆录丶 提交于 2019-12-23 17:43:53

问题


Currently I have something like this:

val q = for {
  department <- departments if department.id === x
  employee <- employees if employee.departmentId === department.id
} yield (department, employee)

which will give me:

(sales, john)
(sales, bob)
(finance, william)
(finance, helen)

I then group the results by departments:

val grouped = results.groupBy(_._1).mapValues(_.map(_._2))

to give me:

(sales -> (john, bob))
(finance -> (wiliam, helen)

I would like to avoid the tuples. Whilst it's quite clear in the simple example it will quickly become unmanageable if I want the department, manager, deputy and list of employees in a structured format. This is especially true if the query and the result processing are not close to each other in the source code.

How can I yield something other than a tuple in the query?

I tried to yield a case class:

case class DeptEmployeeRow(department: Department, employee: Employee)

val q = for {
  department <- departments if department.id === x
  employee <- employee if employee.id
} yield DeptEmployeeRow(department, employee)

but slick doesn't like this. Using a Monomorphic case class and slick's CaseClassShape doesn't work because it only support built in types i.e. I could use:

yield DeptEmployeeRow(department.name, employee.name)

but not

yield DeptEmployeeRow(department, employee)

回答1:


Tuples are in fact quite powerful especially in the context of pattern matching. For example you can access your tuple contents like this:

case class DeptEmployeeRow(department: Department, employee: Employee)

val q = for {
  department <- departments if department.id === x
  employee <- employees if employee.departmentId === department.id
} yield (department, employee)

Access tuple using pattern matching:

val result1: DeptEmployeeRow = db.run(q.result).map {
  case (department, employee) => DeptEmployeeRow(department, employee)
}

Or use a shortcut:

val result2: DeptEmployeeRow = db.run(q.result).map(_.map(DeptEmployeeRow.tupled))

You can take this even further modelling 1:n relations:

case class DeptWithEmployees(department: Department, employees: Seq[Employee])

val result3: DeptWithEmployees = db.run(q.result).map { results =>
  results.groupBy(_._1).map {          // assumption that _._1 is your department id
    case (dept, grp) => DeptWithEmployees(dept, grp.map(_._2))
  }
}


来源:https://stackoverflow.com/questions/35258379/slick-3-return-custom-case-class-from-query

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