问题
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