进行从可选 ID 过滤的 Slick 查询?

Making a Slick query that filters from an optional id?

我想通过 id 查询对象,但如果还提供了 fooId,那么我想将其包含在查询中。

def getById(id: Long, fooIdOpt: Option[Long]): Future[Option[Bar]] = {
  val query = for {
    b <- bars if b.id === id && fooIdOpt.fold(true)(b.fooId === _)
  } yield {            // Compiler error here ^
    b
  }
  db.run(query.result.headOption)
}

这里的问题是 fooIdOpt.fold(true)(b.fooId === _) 需要 return 一个 Rep[Boolean],但我正在用 Boolean 初始化折叠 - 明显违反 fold的方法签名。

但是我似乎无法找到一种方法来将计算结果为 trueRep[Boolean] 作为折叠初始值设定项传递。在黑暗中拍摄,我试过 Rep(true)LiftedLiteral[Boolean](true),但都不行。

我可以完全放弃 fold 并选择:

b <- bars if {
  val rep1 = b.id === id
  fooIdOpt.map(fooId => rep1 && b.fooId === fooId).getOrElse(rep1)
}

但这似乎太复杂了,fooIdOpt match { case Some ... 看起来也好不了多少。

  1. 有没有办法实例化一个总是计算为 trueRep[Boolean] 文字?
  2. 如果没有,是否有替代方案来替代我在上面的 foldmapmatch 的尝试,这将允许我构建一个查询,该查询可以选择性地比较 fooId值?

一个相当不如您的其他选择的替代方案:

(fooIdOpt.toList.map(b.fooId === _) :+ (b.id === id)).reduceLeft(_ && _)

如您所知,foldifEmpty 值类型需要与 b.fooId === _ 的值类型相匹配,即 Rep[Boolean]。一种方法是将 bind 应用于 ifEmpty 值,如下所示:

val query = for {
  b <- bars if b.id === id && fooIdOpt.fold(true.bind)(b.fooId === _)
} yield b