我正在尝试基于一组可能设置或可能未设置的参数来实现返回过滤结果的方法 . 似乎没有条件地链接多个过滤器,即从一个过滤器开始......
val slickFlights = TableQuery[Flights]
val query = slickFlights.filter(_.departureLocation === params("departureLocation").toString)
有条件地在查询中添加另一个过滤器(如果它存在于params的Map中)似乎不起作用......
if (params.contains("arrivalLocation")) {
query.filter(_.arrivalLocation === params("arrivalLocation").toString)
}
可以通过其他方式使用Slick完成这种条件过滤吗?
我遇到了MaybeFilter:https://gist.github.com/cvogt/9193220,这似乎是处理这个问题的一个不错的方法 . 但它似乎不适用于Slick 3.x.
根据Hüseyin的建议,我也尝试了以下方法:
def search(departureLocation: Option[String], arrivalLocation: Option[String]) = {
val query = slickFlights.filter(flight =>
departureLocation.map {
param => param === flight.departureLocation
})
其中 slickFlights
是TableQuery对象 val slickFlights = TableQuery[Flights]
. 但是,这会产生以下编译错误:
value === is not a member of String
Intellij还抱怨= =是一个未知的符号 . 不适用于== .
5 回答
一种更简单的方法,无需理解:
UPDATE: 你可以用
fold
缩短它:为了其他任何试图在Slick中使用可选过滤器的人的利益,请看一下答案:right usage of slick filter . 我终于设法让它使用以下内容:
关键位是 Map 末尾的
.getOrElse(slick.lifted.LiteralColumn(true))
,如果仅设置了departureLocation,则导致Slick如下呈现SQL ...没有它,SQL看起来像......
这显然意味着它没有任何行回来 .
Ross Anthony的(优秀)答案可以通过使用foldLeft进一步推广:
这种方式当引入另一个可选约束时,它可以简单地映射(如pred1和pred2)并添加到preds Iterable,foldLeft将处理其余的 .
我想出了一个新的解决方案:
如果您有查询(
slickFlights
)选项值和选择器,则可以将其与slickFights.filterOption(departureLocation, _.departureLocation)
一起使用 .2019年1月
不再需要发明自己的车轮了!
最后Slick 3.3.0包括以下帮助者:
filterOpt
filterIf
所以,例如: