我有一堆不同的查询可以获取相同的数据,但是应用了不同的标准。
目前,我正在将整个代码库从Query复制到DBIOAction,因为我无法看到如何使这些可组合。这是重复查询的一个示例。
(我已经简化了一些示例,实际代码连接了十三个表):
override val createAction = {
val join = master
.join(child1.filter(child1Filter)).on(_.id === _.id) /* DRY1 */
.joinLeft(child2).on(_._1.id === _.id)
.joinLeft(child3).on(_._1._1.id === _.id)
.joinLeft(child4).on(_._1._1._1.id === _.id)
.joinLeft(child5).on(_._1._1._1._1.id === _.id)
.joinLeft(child6).on(_._1._1._1._1._1.id === _.id)
val query = for {
((((((r, c1), c2), c3), c4), c5), c6) <- join
} yield (r.id, c1.value, c2.value, c3.value, c4.value, c5.value, c6.value) /* DRY2 */
query.result.map( tuples =>
tuples.groupBy(_._1)
.map {
case(id, tuples) => {
val c1 = tuples.map(_._2).distinct.head /* DRY3 */
val c2 = tuples.map(_._3).distinct.head
val c3 = tuples.flatMap(_._4).distinct.headOption
val c4 = tuples.flatMap(_._5).distinct.headOption
val c5 = tuples.flatMap(_._6).distinct.headOption
val c6 = tuples.flatMap(_._7).distinct.headOption
SomeCaseClass(c1, c2, c3, c4, c5, c6)
}
}
)
}
我已经标记了三个部分,其中过滤条件中的一个更改只会更改代码:
DRY1
- 在任何一个加入条件下,我们可以选择joinLeft
或仅join
。这会产生分歧,因为生成的join
具有不同的参数化类型。我们可能还想添加其他标准。
DRY2
- c1
的类型取决于之前加入的类型。
DRY3
- 同样,连接类型会影响结果的映射方式和案例类的创建。
举例来说,一个查询会更改child1
上的联接,另一个查询会更改child2
上的联接。
我缺少一些可以组合并且不会违反DRY的更复杂查询的例子。