Per semplificare diciamo che ho tre tabelle:Qual è un buon modo per combinare l'impaginazione e il raggruppamento senza query in Slick 3.0?
val postTable = TableQuery[Posts]
val postTagTable = TableQuery[PostTags]
val tagTable = TableQuery[Tags]
Un post può avere più tag e postTagTable
contiene solo la relazione.
Ora ho potuto interrogare i post e tag in questo modo:
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))
}
}
Il che mi un Future[Seq[(Post, Seq(Tag))]]
darebbe.
Fin qui tutto bene.
Ma cosa succede se voglio aggiungere l'impaginazione per i post? Poiché uno Post
può avere più Tags
con la query precedente, non so quante righe a take
dalla query, per ottenere, diciamo, 10 Posts
.
Qualcuno conosce un buon metodo per ottenere lo stesso risultato con un numero specifico di post in una singola query?
In realtà non sono nemmeno sicuro di come mi avvicinerei a questo in SQL nativo senza query annidate, quindi se qualcuno ha un suggerimento in quella direzione sarei anche lieto di ascoltarlo.
Grazie!
EDIT
Solo così si sa, che tipo di interrogazione Attualmente sto facendo:
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))
}
}
Ma questo si traduce, ovviamente, in una query nidificate. E questo è quello che vorrei evitare.
EDIT 2
Un'altra soluzione 2-query che sarebbe possibile:
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))
}
}
}
Ma questo avrebbe preso due viaggi al database e utilizza l'operatore in
, quindi è probabilmente non è buono come la query di join.
Qualche suggerimento?
L'aiuto 'groupBy' di Slick non è in questo caso? Se fai 'groupBy' per Post sulla query e poi 'prendi'? – Ixx
Se eseguo il groupBy sulla query, devo usare la mappa per aggregare tutto ciò su cui non ho raggruppato. Quindi se dovessi raggruppare su Post (sulla query), non potrei ottenere i Tag come Elenco ma solo ad es. contali. – thwiegan