2016-03-27 11 views
1

設定されていても設定されていないパラメータのセットに基づいて、フィルタ処理された結果を返すメソッドを実装しようとしています。それは(それがのparamsの地図に存在する場合) Slick 3を使用してオプションのwhere句を使用した動的クエリ

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

は条件付きでいないようクエリに別のフィルタを追加...一つのフィルタでオフに開始する。すなわち、複数のフィルタを連鎖することは条件付きで可能であるように見えるしていません...

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

この種の条件フィルタリングは、他の方法でSlickを使用して行うことができますか?

私はMaybeFilter:https://gist.github.com/cvogt/9193220を見つけました。これは正確にこれを処理するためのまともなアプローチのようです。しかし、以下のフセインの提案に続きスリック3.xの

で動作するようには思えない、私はまた、次のことを試してみました:

slickFlightsはTableQueryオブジェクト val slickFlights = TableQuery[Flights]ある
def search(departureLocation: Option[String], arrivalLocation: Option[String]) = { 
    val query = slickFlights.filter(flight => 
     departureLocation.map { 
      param => param === flight.departureLocation 
     }) 

。ただし、次のコンパイルエラーが発生します。

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 

キービットは、たとえばだけdepartureLocationが設定されている場合は、次のようにSQLをレンダリングするスリック原因マップの端に.getOrElse(slick.lifted.LiteralColumn(true))ています...

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 === _) 
} 
関連する問題