Slick 3.0.0:如何查询一对多/多对多关系
Posted
技术标签:
【中文标题】Slick 3.0.0:如何查询一对多/多对多关系【英文标题】:Slick 3.0.0: How to query one-to-many / many-to-many relations 【发布时间】:2015-08-14 13:12:49 【问题描述】:大约一年前,对于 slick 2.x (scala slick one-to-many collections),基本上也有人问过同样的问题。我想知道反应性光滑的发布是否有任何进展。
假设我们有三个表。 library
、book
和 library_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])]
类型的结果?编写此类查询的“巧妙方式”是什么?
【问题讨论】:
【参考方案1】: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
【讨论】:
正如 Sky 之前在评论中提到的,在光滑的 atm 中没有办法做到这一点。我想你提出的.groupBy
方法是目前的方法。
@Roman 如果图书馆没有书,这会返回一个空的Seq
吗?如果是这样,它可能与预期不太相符。
@acjay:在这种情况下,这确实会导致一个空的Seq
。如果您想在结果中包含所有图书馆,无论它们是否有书籍,您都可以使用外连接而不是内连接(joinLeft
,joinRight
用巧妙的术语)。如果这不是您想要的,请随时提出后续问题:)
@Roman 我 认为 我已经弄清楚了我的情况(与您的问题类似)。我使用joinLeft
,然后在运行查询后,我正在执行.groupBy(_._1).mapValues(_.flatMap(_._2)).toSeq
以到达Seq[(OneTable, Seq[ManyTable])]
。
@acjay 很高兴听到。竖起大拇指!【参考方案2】:
对于您想要映射到的内容,db.run 在您的情况下返回 Future(of something)、Future[Seq[(Library, Seq[Book])]]。映射未来时,您可以访问 Seq,并且可以将其转换为其他东西以获得新的未来。
【讨论】:
感谢您的回答。不幸的是,这不是我想要的。我刚刚更新了我的问题并试图更具体一点。以上是关于Slick 3.0.0:如何查询一对多/多对多关系的主要内容,如果未能解决你的问题,请参考以下文章