I am still fairly new to slick and very much learning.
I an trying to create a search functionality that would be quite simple with plain SQL. However, I am hitting some obstacles when I am trying to do the same with Slick.
Trying to go by example from here: http://slick.lightbend.com/doc/3.2.1/queries.html#sorting-and-filtering i am starting to build a function as follows:
private def schoolSearchBaseQuery(drop: Long, take: Long) = {
(for {
schools <- Schools.schools.filter(_.deletedAt.isEmpty)
} yield schools).drop(drop).take(take)
}
def search(schoolSearchCriteria: SchoolSearchCriteria, drop: Long = 0, take: Long = 100): Future[Seq[School]] = {
val q = schoolSearchBaseQuery(drop, take) filter { school =>
List(
schoolSearchCriteria.name.map(n => school.name like s"%$n%")
)
}
db.run(q.result)
}
But this seem to be not right:
[error] /Users/ShurikAg/Dev/indago/indago-api/app/dao/SchoolDao.scala:97:47: inferred type arguments [List[Option[slick.lifted.Rep[Boolean]]]] do not conform to method filter's type parameter bounds [T <: slick.lifted.Rep[_]]
[error] val q = schoolSearchBaseQuery(drop, take) filter { school =>
[error] ^
[error] /Users/ShurikAg/Dev/indago/indago-api/app/dao/SchoolDao.scala:97:63: type mismatch;
[error] found : model.Schools => List[Option[slick.lifted.Rep[Boolean]]]
[error] required: model.Schools => T
[error] val q = schoolSearchBaseQuery(drop, take) filter { school =>
Also, IntelliJ complains about this:
I think I am misunderstanding something.
For a reference School definition related code:
package model
import driver.PGDriver.api._
import org.joda.time.DateTime
import play.api.libs.json._
import slick.lifted.Tag
import format.DateTimeFormat._
import model.media.Medias
case class School(id: Option[Int] = None,
addressId: Option[Int] = None,
name: String,
about: Option[String] = None,
numberOfStudents: Option[Int] = None,
websiteUrl: Option[String] = None,
mediaId: Option[Int] = None,
slug: String,
shortDescription: Option[String] = None,
ready: Boolean,
classrooms: Option[Int] = None,
yearEstablished: Option[String] = None,
displayCopyright: Boolean,
createdAt: DateTime = DateTime.now,
updatedAt: DateTime = DateTime.now,
deletedAt: Option[DateTime] = None,
createdBy: Option[String] = None,
updatedBy: Option[String] = None,
dliNumber: Option[String] = None)
object Schools {
val schools = TableQuery[Schools]
implicit lazy val schoolFormat: Format[School] = Json.format[School]
Json.toJson[DateTime](DateTime.now)
}
class Schools(tag: Tag) extends Table[School](tag, "school") {
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
def addressId = column[Option[Int]]("address_id")
def name = column[String]("name", O.SqlType("character varying(255)"))
def about = column[Option[String]]("about", O.SqlType("text"))
def numberOfStudents = column[Option[Int]]("number_of_students")
def websiteUrl = column[Option[String]]("website_url", O.SqlType("character varying(100)"))
def mediaId = column[Option[Int]]("media_id")
def slug = column[String]("slug", O.SqlType("character varying(255)"))
def shortDescription = column[Option[String]]("short_description", O.SqlType("character varying(255)"))
def ready = column[Boolean]("ready")
def classrooms = column[Option[Int]]("classrooms")
def yearEstablished = column[Option[String]]("year_established", O.SqlType("character varying(4)"))
def displayCopyright = column[Boolean]("display_copyright")
def createdAt = column[DateTime]("createdat")
def updatedAt = column[DateTime]("updatedat")
def deletedAt = column[Option[DateTime]]("deletedat")
def createdBy = column[Option[String]]("createdby", O.SqlType("character varying(255)"))
def updatedBy = column[Option[String]]("updatedby", O.SqlType("character varying(255)"))
def dliNumber = column[Option[String]]("dli_number", O.SqlType("character varying(50)"))
override def * =
(
id.?,
addressId,
name,
about,
numberOfStudents,
websiteUrl,
mediaId,
slug,
shortDescription,
ready,
classrooms,
yearEstablished,
displayCopyright,
createdAt,
updatedAt,
deletedAt,
createdBy,
updatedBy,
dliNumber
) <> (School.tupled, School.unapply)
def addressIdUniqueIdx = index("school_address_id_uidx", addressId, unique = true)
def application =
foreignKey("school_address_id_fkey", addressId, Addresses.addresses)(
_.id.?,
onUpdate = ForeignKeyAction.Cascade,
onDelete = ForeignKeyAction.Restrict
)
def mediaIdUniqueIdx = index("school_media_id_uidx", mediaId, unique = true)
def logo =
foreignKey("school_media_id_fkey", mediaId, Medias.medias)(
_.id.?,
onUpdate = ForeignKeyAction.Cascade,
onDelete = ForeignKeyAction.Restrict
)
def slugUniqueIdx = index("school_slug_uidx", slug, unique = true)
}
And SchooSearchCriteria:
case class SchoolSearchCriteria(name: Option[String])
The criteria eventually going to be more complex than just a single field. I and just trying to figure out the mechanism for now.
Is it even the right direction to create search queries like that, given that the base query will eventually include more than a single table or even a single join?
for { x <- y } yield x
is justy
. – Dmytro MitinSchools
andSchools.schools
. – Dmytro Mitin