filter multiple optional fields with slick 3.0

1,043 views
Skip to first unread message

Eric Swenson

unread,
Jun 19, 2015, 5:03:26 PM6/19/15
to scala...@googlegroups.com
This is not a new topic, but I have yet to find or create a working example of how to perform a filter or multiple conditions OR'ed together, where the clauses are only included if an optional filter parameter is supplied.

I've successfully used the following construct in Slick 2.0, but can't get it to work in Slick 3.0:

case class MaybeFilter[X, Y](val query: slick.lifted.Query[X, Y, Seq]) {

  def filter(op: Option[_])(f:(X) => Column[Option[Boolean]]) = {

    op map { o => MaybeFilter(query.filter(f)) } getOrElse { this }

  }

}


I'm trying to use it like this:


val a: Option[String] = Some("foo")

MaybeFilter(orders).filter(a)(n => o => o.name === n)


I get errors like this:


ambiguous reference to overloaded definition, both method filter in class MaybeFilter of type (op: Option[_])(f: com.example.models.OrderTable ⇒ slick.driver.MySQLDriver.api.Column[Option[Boolean]])<error> and method filter in class MaybeFilter of type (op: Option[_])(f: com.example.models.OrderTable ⇒ slick.driver.MySQLDriver.api.Column[Option[Boolean]])com.example.models.MaybeFilter[com.example.models.OrderTable,com.example.models.OrderTable#TableElementType] match argument types (Option[String])


This question has been asked and answered (with differing solutions) so many times over the last few years, it seems the hello-slick-3.0 (and subsequent versions) should show how to do this, and the documentation on Slick should provide a description of how to do this, together with some example code.


If anyone knows how to do this, would you please provide a complete working example? I ask because the various code fragments you can find on stackoverflow frequently don't compile due to missing or incorrect (and difficult to guess) imports. 


Again, I have working code in 2.0, but I cannot get it to work in 3.0.  Thanks.  

Михаил Ионкин

unread,
Sep 30, 2018, 6:31:00 AM9/30/18
to Slick / ScalaQuery
See it, it's help me. Sorry for bad class names.
package main

import slick.jdbc.H2Profile.api._
import slick.lifted.CanBeQueryCondition

import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}

case class X(name: String, id: Int = 0)

class XTable(tag: Tag) extends Table[X](tag, "x_table") {
 
def id: Rep[Int] = column[Int]("id", O.PrimaryKey, O.AutoInc)
 
def name: Rep[String] = column[String]("name")

 
override def * = (name, id).mapTo[X]
}
case class XFilter(name: Option[String] = None, id: Option[Int] = None)

case class MaybeFilter[X, Y, C[_]](query: slick.lifted.Query[X, Y, C]) {
 
def filter[T,R: CanBeQueryCondition](data: Option[T])(f: T => X => R): MaybeFilter[X, Y, C] = {
    data
.map(v => MaybeFilter(query.withFilter(f(v)))).getOrElse(this)
 
}
}

object Main extends App {
 
val db = Database.forConfig("chapter01")
 
val someTable = TableQuery[XTable]
 
println(0)

 
def myFilter(xf: XFilter) {
   
db.run(someTable.schema.create).onComplete {
     
case Success(_) => {
       
println(1)
       
db.run(someTable ++= Seq(X("haba"), X("hab"), X("ab"), X("abah"))).onComplete {
         
case Success(_) => {
           
println(2)
           
val mf = MaybeFilter(someTable).filter(xf.name)(name => t => t.name like name).query.result
           
db.run(mf).onComplete {
             
case Success(value) => println(value)
             
case Failure(exception) => exception.printStackTrace()
           
}
         
}
         
case Failure(exception) => exception.printStackTrace()
       
}
     
}
     
case Failure(exception) => exception.printStackTrace()
   
}
 
}
 
myFilter(XFilter(Some("hab%"), Some(1)))
 
Thread.sleep(2000)
}


Reply all
Reply to author
Forward
0 new messages