圆滑的一对多和分组
Slick one to many and grouping
我正在尝试使用 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
的 class,它看起来像;
case class FullReview(r: Review, user: User, evts: Seq[ReviewEvent])
假设每个模型都有正确的表,我正在尝试使用连接和分组依据的组合来获取 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
类型时,这似乎会产生。我在这里做错了什么?
经过一些修补,我认为在客户端上进行聚合会更好。这间接意味着,如果 table ETable
上的 100 行与 RTable
上的一行匹配,您将在客户端上获得多行。然后,客户端必须实现自己的聚合,以通过 Review
.
对所有 ReviewEvent
进行分组
就分页而言,您可以这样做;
def withUser(page: Int, pageSize: Int) = for {
(r, u) <- RTable.drop(page * pageSize).take(pageSize) join UTable on (_.userId === _.id)
}
我想现在这已经足够优雅了。如果有人有更好的答案,我很乐意听到。
如果我理解正确,你可以使用下面的例子:
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
}
}
如果你想为这个请求添加分页,我已经回答了 and here 是完整的例子。
我正在尝试使用 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
的 class,它看起来像;
case class FullReview(r: Review, user: User, evts: Seq[ReviewEvent])
假设每个模型都有正确的表,我正在尝试使用连接和分组依据的组合来获取 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
类型时,这似乎会产生。我在这里做错了什么?
经过一些修补,我认为在客户端上进行聚合会更好。这间接意味着,如果 table ETable
上的 100 行与 RTable
上的一行匹配,您将在客户端上获得多行。然后,客户端必须实现自己的聚合,以通过 Review
.
ReviewEvent
进行分组
就分页而言,您可以这样做;
def withUser(page: Int, pageSize: Int) = for {
(r, u) <- RTable.drop(page * pageSize).take(pageSize) join UTable on (_.userId === _.id)
}
我想现在这已经足够优雅了。如果有人有更好的答案,我很乐意听到。
如果我理解正确,你可以使用下面的例子:
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
}
}
如果你想为这个请求添加分页,我已经回答了