Slick 3.0.0:如何查询一对多/多对多关系

Slick 3.0.0: How to query one-to-many / many-to-many relations

基本相同的问题已经在大约一年前问过 slick 2.x (scala slick one-to-many collections)。我想知道 reactive slick 的发布是否有任何进展。

假设我们有三个表。 librarybooklibrary_to_book,其中图书馆有很多书。我想要的是图书馆及其书籍的列表。在 Scala 中,这类似于 Seq[(Library, Seq[Book])]。我的查询如下:

val q = (for {
  l   <- libraries
  ltb <- libraryToBooks if l.id === ltb.libraryId
  b   <- books if ltb.bookId === b.id
} yield (l, b)
db.run(q.result).map( result => ??? )

results 在这种情况下是类型 Seq[(Library, Book)]。我必须如何更改我的查询才能获得 Seq[(Library, Seq[Book])] 类型的结果?编写此类查询的 "slick way" 是什么?

到你想要映射到的地方,db.run returns 一个 Future(of something),一个 Future[Seq[(Library, Seq[Book])]] 在你的例子中。当映射到未来时,您可以访问 Seq,您可以将其转换为其他东西以获得新的未来。

IMO 你的代码看起来不错。这真的取决于你觉得什么更具可读性。或者,您也可以使用 join

val findBooksQuery = libraries
  .join(libraryToBooks).on(_.id === _.libraryId)
  .join(books).on(_.id === _._2.bookId)
  .result

val action = (for {
  booksResult <- findBooksQuery
} yield {
  booksResult.map { row =>
    val (libraryTableRow, libraryToBooksTableRow) = row._1
    val booksTableRow = row._2
    // TODO: Access all data from the rows and construct desired DS
  }
}

db.run(action)

然后您可以对特定键执行 groupBy 以获得您正在寻找的数据结构类型。在这种情况下,它会更加进化,因为它连接了三个表。例如,将以下内容添加到您的查询中:

val findBooksQuery = libraries
  .join(libraryToBooks).on(_.id === _.libraryId)
  .join(books).on(_.id === _._2.bookId)
  // To group by libraries.id
  .groupBy(_._1.id)
  .result