2016-03-27 1 views
1

Я пытаюсь реализовать метод возврата отфильтрованных результатов на основе набора параметров, которые могут быть или не могут быть установлены. Это не похоже, цепочки несколько фильтров можно условно, то есть начинать с одного фильтра ...Динамический запрос с дополнительными предложениями, использующими Slick 3

val slickFlights = TableQuery[Flights] 
val query = slickFlights.filter(_.departureLocation === params("departureLocation").toString) 

условно добавив еще один фильтр запроса (если он существует в Карте Params) не кажется для работы ...

if (params.contains("arrivalLocation")) { 
     query.filter(_.arrivalLocation === params("arrivalLocation").toString) 
} 

Можно ли это условно фильтровать, используя Slick другими способами?

Я столкнулся с MaybeFilter: https://gist.github.com/cvogt/9193220, который, кажется, подходит для решения именно этого. Однако это не похоже на работу с Slick 3.x

После предложений huseyın в ниже, я также попытался следующие:

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 также жалуется на наличие === неизвестного символа. Не работает с ==.

ответ

3

В интересах любого другого, кто пытается получить дополнительные фильтры, работающие в Slick, посмотрите здесь ответ: right usage of slick filter. Я, наконец, удалось получить его работу со следующим:

def search(departureLocation: Option[String], arrivalLocation: Option[String]) = { 
    val query = for { 
    flight <- slickFlights.filter(f => 
     departureLocation.map(d => 
     f.departureLocation === d).getOrElse(slick.lifted.LiteralColumn(true)) && 
     arrivalLocation.map(a => 
     f.arrivalLocation === a).getOrElse(slick.lifted.LiteralColumn(true)) 
    ) 
    } yield flight 

Ключ немного будучи .getOrElse(slick.lifted.LiteralColumn(true)) на конце карты, что приводит к Slick, чтобы сделать SQL следующим образом, если, например, только departureLocation установлен ...

select * from `flight` 
where (`departureLocation` = 'JFK') and true 

тогда как без него SQL выглядел ...

select * from `flight` 
where (`departureLocation` = 'JFK') and (`arrivalLocation` = '') 

, который, очевидно, имел в виду, что он вернулся без каких-либо строк.

8

Более простой подход без для понимания:

import slick.lifted.LiteralColumn 

val depLocOpt = Option[Long] 
val slickFlights = TableQuery[Flights] 
val query = slickFlights.filter { sf => 
    if (depLocOpt.isDefined) sf.departureLocation === depLocOpt.get 
    else      LiteralColumn(true) 
} 

UPDATE: вы можете сократить его больше с fold:

val depLocOpt = Option[Long] 
val slickFlights = TableQuery[Flights] 
val query = slickFlights.filter { sf => 
    depLocOpt.fold(true.bind)(sf.departureLocation === _) 
}