光滑的一对多和分组

时间:2016-10-25 14:39:37

标签: scala slick

我正在尝试使用Slick 3.1.0模拟以下内容;

case class Review(txt: String, userId: Long, id: Long)
case class User(name: String, id: Long)
case class ReviewEvent(event: String, reviewId: Long)

我需要填充一个名为FullReview的类,它看起来像;

case class FullReview(r: Review, user: User, evts: Seq[ReviewEvent])

假设每个模型都有正确的表格,我试图使用join和group by的组合来获取FullReview,如下所示:

val withUser = for {
  (r, u) <- RTable join UTable on (_.userId === _.id)
}

val withUAndEvts = (for {
  ((r, user), evts) <- withUser joinLeft ETable on {
    case ((r, _), ev) => r.id === ev.reviewId
  }
} yield (r, user, events)).groupBy(_._1._id)

当我看到一个嵌套的Query类型时,这似乎会产生。我在这里做错了什么?

2 个答案:

答案 0 :(得分:1)

如果我理解正确,您可以使用以下示例:

val users = TableQuery[Users]
val reviews = TableQuery[Reviews]
val events = TableQuery[ReviewEvents]

override def findAllReviews(): Future[Seq[FullReview]] = {
  val query = reviews
    .join(users).on(_.userId === _.id)
    .joinLeft(events).on(_._1.id === _.reviewId)

  db.run(query.result).map { a =>
    a.groupBy(_._1._1.id).map { case (_, tuples) =>
      val ((review, user), _) = tuples.head
      val reviewEvents = tuples.flatMap(_._2)
      FullReview(review, user, reviewEvents)
    }.toSeq
  }
}

如果您想为此请求添加分页,我已经回答了here,而here就是完整示例。

答案 1 :(得分:0)

通过一些修修补补,我认为在客户端进行聚合会更好。间接的意思是,如果表ETable上的100行与RTable上的单行匹配,那么客户端上将获得多行。然后,客户端必须实施自己的聚合,以便按ReviewEvent对所有Review进行分组。

就分页而言,你可能会做类似的事情;

def withUser(page: Int, pageSize: Int) = for {
  (r, u) <- RTable.drop(page * pageSize).take(pageSize) join UTable on (_.userId === _.id)
}

我想现在这个很优雅。如果有人有更好的答案,我会很高兴听到它。