srvy srvy - 2 months ago 17
Scala Question

Scala slick: build query conditionally

I am new to Scala and I am using Slick 3.1 and have this query:

val dBIOAction = for {
user <- users.filter(_.email === email)
company <- companies.filter(_.userid === user.id)
} yield (user, company)


Not all users will have entries in companies. Still, I want to return users even if there is no corresponding entry in company. Currently, if no entry in company, I get empty result.

Query roughly translates to:

res46: String = select x2."LASTNAME", x3."NAME", x2."FIRSTNAME", x3."WEBSITE", x3."USERID", x2."EMAIL", x2."ID", x3."ID" from "Users" x2, "Companies" x3 where (x2."EMAIL" = 'a@a.com') and (x3."USERID" = x2."ID")

Looks like company clause is included always - can that be included conditionally ? If not, how else I can achieve the desired effect ?

Answer

Simply use an applicative join rather than a monadic one (since you want a LEFT JOIN rather than an INNER JOIN:

val usersWithCompany = users.joinLeft(companies).on(_.id === _.userId)
val dBIOAction = for {
  (user, company) <- usersWithCompany.filter(_._1.email === email)
} yield (user, company)