0

我正在尝试使用 Quill 来实现以下 PostgreSQL 查询的功能:

select books.*, array_agg(authors.name) from books 
join authors_books on(books.id = authors_books.book_id)
join authors on(authors.id = authors_books.author_id)
group by books.id

现在我在我的 Quill 版本中有这个:

val books = quote(querySchema[Book]("books"))
val authorsBooks = quote(querySchema[AuthorBook]("authors_books"))
val authors = quote(querySchema[Author]("authors"))

val q: db.Quoted[db.Query[(db.Query[Book], Seq[String])]] = quote{
        books
            .join(authorsBooks).on(_.id == _.book_id)
            .join(authors).on(_._2.author_id == _.id)
            .groupBy(_._1._1.id)
            .map {
                case (bId, q) => {
                    (q.map(_._1._1), unquote(q.map(_._2.name).arrayAgg))
                }
            }
    }

如何摆脱结果中的嵌套查询(db.Query[Book])并获得一本书?

4

1 回答 1

1

我可能对 SQL 有点生疏,但您确定您的查询有效吗?特别是我发现您select books.*group by books.id直接返回未分组的字段时这样做很可疑。尝试直接翻译错误的查询是导致事情出错的原因

解决它的一种方法是group by通过所有领域进行。假设Book声明为:

case class Book(id: Int, name: String)

你可以做

  val qq: db.Quoted[db.Query[((Index, String), Seq[String])]] = quote {
    books
      .join(authorsBooks).on(_.id == _.book_id)
      .join(authors).on(_._2.author_id == _.id)
      .groupBy(r => (r._1._1.id, r._1._1.name))
      .map {
        case (bId, q) => {
          // (Book.tupled(bId), unquote(q.map(_._2.name).arrayAgg)) // doesn't work
          (bId, unquote(q.map(_._2.name).arrayAgg))
        }
      }
  }

  val res = db.run(qq).map(r => (Book.tupled(r._1), r._2))

不幸的是,您似乎无法Book.tupled在内部申请,quote因为您收到错误

单子组合不能使用应用连接来表达

但是您可以在db.run致电后轻松完成此操作以取回您的Book.

另一种选择是进行分组Book.id,然后Book再次加入表以获取所有字段。如果里面有很多字段,这实际上可能更干净,更快Book

于 2017-12-18T10:39:25.367 回答