为简化起见,假设我有三个表:
val postTable = TableQuery[Posts]
val postTagTable = TableQuery[PostTags]
val tagTable = TableQuery[Tags]
一篇文章可以有多个标签,并且postTagTable
只包含关系。
现在我可以像这样查询帖子和标签:
val query = for {
post <- postTable
postTag <- postTagTable if post.id === postTag.postId
tag <- tagTable if postTag.tagId === tag.id
} yield (post, tag)
val postTags = db.run(query.result).map {
case result: Seq[(Post,Tag)] =>
result.groupBy(_._1).map {
case (post, postTagSeq) => (post, postTagSeq.map(_._2))
}
}
这会给我一个Future[Seq[(Post, Seq(Tag))]]
.
到目前为止,一切都很好。
但是,如果我想为帖子添加分页怎么办?由于上面的查询Post
可以有多个Tags
,我不知道查询中有多少行take
,为了得到,比如说 10 Posts
。
有谁知道在单个查询中使用特定数量的帖子获得相同结果的好方法?
实际上,我什至不确定在没有嵌套查询的情况下如何在本机 SQL 中处理这个问题,所以如果有人在这个方向上有建议,我也会很高兴听到它。
谢谢!
编辑
只是让你知道,我目前正在做什么样的查询:
val pageQuery = postTable drop(page * pageSize) take(pageSize)
val query = for {
pagePost <- pageQuery
post <- postTable if pagePost.id === post.id
postTag <- postTagTable if post.id === postTag.postId
tag <- tagTable if postTag.tagId === tag.id
} yield (post, tag)
val postTags = db.run(query.result).map {
case result: Seq[(Post,Tag)] =>
result.groupBy(_._1).map {
case (post, postTagSeq) => (post, postTagSeq.map(_._2))
}
}
但这显然会导致嵌套查询。这是我想避免的。
编辑 2
另一个可能的 2 查询解决方案:
val pageQuery = postTable drop(page * pageSize) map(_.id) take(pageSize)
db.run(pageQuery.result) flatMap {
case ids: Seq[Int] =>
val query = for {
post <- postTable if post.id inSetBind ids
postTag <- postTagTable if post.id === postTag.postId
tag <- tagTable if postTag.tagId === tag.id
} yield (post, tag)
val postTags = db.run(query.result).map {
case result: Seq[(Post,Tag)] =>
result.groupBy(_._1).map {
case (post, postTagSeq) => (post, postTagSeq.map(_._2))
}
}
}
但这需要两次访问数据库并使用in
运算符,因此它可能不如连接查询好。
有什么建议么?