Reputation: 559
I pretty new in using slick and now I faced with the issue how to retrieve some data from two tables. I have one table
class ExecutionTable(tag: Tag) extends Table[ExecTuple](tag, "execution") {
val id: Rep[String] = column[String]("id")
val executionDefinitionId: Rep[Long] = column[Long]("executionDefinitionId")
// other fields are omitted
def * = ???
}
and another table
class ServiceStatusTable(tag: Tag)
extends Table[(String, Option[String])](tag, "serviceStatus") {
def serviceId: Rep[String] = column[String]("serviceId")
def detail: Rep[String] = column[String]("detail")
def * = (serviceId, detail.?)
}
In Dao I convert data from this two tables to a business object
case class ServiceStatus(
id: String,
detail: Option[String] = None, //other fields
)
like this
private lazy val getServiceStatusCompiled = Compiled {
(id: Rep[String], tenantId: Rep[String]) =>
for {
exec <- getExecutionById(id, tenantId)
status <- serviceStatuses if exec.id === status.serviceId
} yield mapToServiceStatus(exec, status)
}
and later
def getServiceStatus(id: String, tenantId: String)
: Future[Option[ServiceStatus]] = db
.run(getServiceStatusCompiled(id, tenantId).result.transactionally)
.map(_.headOption)
The problem is that not for all entries from table execution
exists entry in table serviceStatus
. I cannot modify table execution
and add to it field details
as it is only service specific.
When I run query in case when for entry from execution
exists entry in serviceStatus
all works as expected. But if there is no entry in serviceStatus
, Future[None] is returned.
Question: Is there any option to obtain status
in for comprehension as Option depending on existing entry in table serviceStatus
or some else workaround?
Upvotes: 0
Views: 365
Reputation: 8866
Usually, in case when join condition does not find corresponding record in the "right" table but the result should still contain the row from "left" table, left join is used. In your case you can do something like:
Execution
.filter(...execution table filter...)
.joinLeft(ServiceStatus).on(_.id===_.serviceId)
This gives you pair of
(Execution, Rep[Option[ServiceStatus]])
and after query execution:
(Execution, Option[ServiceStatus])
Upvotes: 1