To simplify, let's say that I have three tables:
val postTable = TableQuery[Posts] val postTagTable = TableQuery[PostTags] val tagTable = TableQuery[Tags]
A single post can have multiple tags, and postTagTable just contains a relation.
Now I can request messages and tags as follows:
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)) } }
Which would give me Future[Seq[(Post, Seq(Tag))]] .
So far so good.
But what if I want to add pagination for messages? Since one Post can have several Tags with the above request, I donβt know how many lines in take from the request to get, say, 10 Posts .
Does anyone know a good way to get the same result with a certain number of posts in a single query?
I'm not even sure how I would approach this in my native SQL without nested queries, so if anyone has a suggestion in this direction, I would also be happy to hear it.
Thanks!
EDIT
Just so you know what request I'm doing right now:
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)) } }
But this obviously leads to a subquery. And that I would like to avoid.
EDIT 2
Another solution with two queries:
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)) } } }
But this will require two trips to the database and use the in operator, so it is probably not as good as the connection request.
Any suggestions?