Sql 什么';在Slick 3.0中,将分页和非查询分组结合起来的好方法是什么?

Sql 什么';在Slick 3.0中,将分页和非查询分组结合起来的好方法是什么?,sql,scala,slick,slick-3.0,Sql,Scala,Slick,Slick 3.0,为了简化,假设我有三个表: val postTable = TableQuery[Posts] val postTagTable = TableQuery[PostTags] val tagTable = TableQuery[Tags] 一篇文章可以有多个标记,postTagTable只包含关系 现在我可以像这样查询帖子和标签: val query = for { post <- postTable postTag <- postTagTable if post.

为了简化,假设我有三个表:

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))
        }
}
  def findPagination(from: Int, to: Int): Future[Seq[(Post, Seq[Tag])]] = {
    val query:DBIO[Seq[(Album,Seq[Genre])]] = postRepository.findAll(from, to).flatMap{posts=>
      DBIO.sequence(
        posts.map{ post=>
          tagRepository.findByPostId(post.id).map(tags=>(post,tags))
        }
      )
    }
    db.run(query)
  }
但这显然会导致嵌套查询。这就是我想要避免的

编辑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))
                     }
        }
 }
val pageQuery=postTable drop(page*pageSize)map(u.id)take(pageSize)
db.run(pageQuery.result)flatMap{
案例ID:Seq[Int]=>
val query=for{
post您可以这样做:

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))
        }
}
  def findPagination(from: Int, to: Int): Future[Seq[(Post, Seq[Tag])]] = {
    val query:DBIO[Seq[(Album,Seq[Genre])]] = postRepository.findAll(from, to).flatMap{posts=>
      DBIO.sequence(
        posts.map{ post=>
          tagRepository.findByPostId(post.id).map(tags=>(post,tags))
        }
      )
    }
    db.run(query)
  }
内部
PostRepository

def findAll(from: Int, limit: Int): DBIO[Seq[Post]] = postTable.drop(from).take(limit).result
  def findByPostId(id: Int): DBIO[Seq[Tag]] = {
    val query = for {
      tag <- tagTable
      pstTag <- postTagTable if pstTag.postId === id && tag.id === pstTag.tagId
    } yield tag
    query.result
  }
内部
TagRepository

def findAll(from: Int, limit: Int): DBIO[Seq[Post]] = postTable.drop(from).take(limit).result
  def findByPostId(id: Int): DBIO[Seq[Tag]] = {
    val query = for {
      tag <- tagTable
      pstTag <- postTagTable if pstTag.postId === id && tag.id === pstTag.tagId
    } yield tag
    query.result
  }
也许在您的情况下,预编译这个查询更有效
我也有同样的问题。可能还很有趣:

        val query = for {
      ((p, pt), t) <- posts.filter({x => x.userid === userId}).sortBy({x=>x.createdate.desc}).take(count).
                      joinLeft (postsTags).on((x, y)=>x.postid === y.postid).
                      joinLeft (tags).on(_._2.map(_.tagid) === _.tagid)
    } yield (p.?, t.map(_.?))
    //val query = posts filter({x => x.userid === userId}) sortBy({x=>x.createdate.desc}) take(count)
    try db.run(query result)
    catch{
      case ex:Exception => {
        log error("ex:", ex)
        Future[Seq[(Option[PostsRow], Option[Option[TagsRow]])]] {
          Seq((None, None))
        }
      }
    }
}

它返回如下顺序:
Seq[(Post,Seq[Tag]),(Post,Seq[Tag])…]

在这种情况下,Slick的
groupBy
没有帮助吗?如果你在查询中按Post进行
groupBy
,然后按Post进行
take
?如果我在查询中按groupBy,我需要使用map来聚合我没有分组的所有内容。因此,如果我要在Post上分组(在查询中),我无法将标记作为列表获取,但只能对它们进行计数。但即使它只命中数据库一次,也会导致n+1个语句(其中n是pageSize),不是吗?是的,您对数据库的命中率为n+1。1命中率为“分页”posts和n用于获取每个postOK的标记,因此您可以避免嵌套查询,但对数据库进行两次往返更糟糕