是否有更可读或更惯用的方式用光滑表达此查询?

时间:2016-10-28 20:30:41

标签: slick slick-3.0

我正在尝试使用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 

感觉笨拙且难以阅读。是否有更简洁的方式用光滑的方式编写此查询?

2 个答案:

答案 0 :(得分:0)

我个人更喜欢方法风格,使用部分函数来显示行名称:

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

我希望有所帮助!

答案 1 :(得分:0)

为了理解救援。内部和交叉连接可以表示为“monadic连接”。以下是使用内部联接:

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了解更多示例。