是否有更易读或更惯用的方式来表达这个查询?

Is there a more readable or more idiomatic way of expressing this query with slick?

我正在尝试使用 slick 3.1.1 执行与以下 SQL 查询等效的操作:

SELECT 
    r.*
FROM Resource r
INNER JOIN User u ON u.id = r.owner_id
INNER JOIN UserCredentials uc ON uc.user_id = u.id 
WHERE r.id = <resource id> 

我是这样表达查询的:

(for ( ((resource,_),_) <- resources
                              join users on (_.userId === _.id)
                              join userCredentials on (_._2.id === _.userId))
  yield resource).filter(_.id === resourceId).result.headOption 

感觉笨重难读。是否有更简洁的方式来使用 slick 编写此查询?

我个人比较喜欢method-style,使用偏函数来显示行名:

resources.filter(_.id === resourceId).join(users).on {
  case (resource, user) => resource.userId === user.id
}.join(userCredentials).on {
  case ((_, user), userCredentials) => user.id === userCredentials.userId
}.filter {
  case ((resource, _), _) => resource.id === resourceId
}.map {
  case ((resource, _), _) => resource
}.result.headOption

您也可以过滤 resources 作为您的第一步,这会让事情变得更清晰:

resources.filter(_.id === resourceId).join(users).on {
  case (resource, user) => resource.userId === user.id
}.join(userCredentials).on {
  case ((_, user), userCredentials) => user.id === userCredentials.userId
}.map {
  case ((resource, _), _) => resource
}.result.headOption

希望对您有所帮助!

求修真解救。内连接和交叉连接可以表示为"monadic joins"。以下是使用内部联接:

val query = for {
  r  <- resources if r.id === resourceId
  u  <- users if u.id === r.ownerId
  uc <- userCredentials if uc.userId === u.id
} yield r

查看 slick docs 了解更多示例。