Slick 3.0 Использование фильтров для запроса данных

У меня есть класс case, как показано ниже:

case class PowerPlantFilter(
  powerPlantType: Option[PowerPlantType],
  powerPlantName: Option[String],
  orgName: Option[String],
  page: Int,
  onlyActive: Boolean
)

Мое сопоставление таблиц выглядит следующим образом:

class PowerPlantTable(tag: Tag) extends Table[PowerPlantRow](tag, "powerPlant") {
    def id            = column[Int]("powerPlantId", O.PrimaryKey)
    def orgName       = column[String]("orgName")
    def isActive      = column[Boolean]("isActive")
    def minPower      = column[Double]("minPower")
    def maxPower      = column[Double]("maxPower")
    def powerRampRate = column[Option[Double]]("rampRate")
    def rampRateSecs  = column[Option[Long]]("rampRateSecs")
    def powerPlantType= column[PowerPlantType]("powerPlantType")
    def createdAt     = column[DateTime]("createdAt")
    def updatedAt     = column[DateTime]("updatedAt")

    def * = {
      (id, orgName, isActive, minPower, maxPower,
        powerRampRate, rampRateSecs, powerPlantType, createdAt, updatedAt) <>
        (PowerPlantRow.tupled, PowerPlantRow.unapply)
    }
  }

Я хотел бы просмотреть фильтр и заполнить динамический запрос! Кроме того, я хотел бы использовать аналогичный оператор в моем результирующем SQL для типов String.

Таким образом, в моем случае выше orgName в моем PowerPlantFilter должен быть проверен на существование, и если да, он должен создать аналогичный оператор в результирующем SQL!

Вот моя первая попытка, но, очевидно, она терпит неудачу!

val q4 = all.filter { powerPlantTable =>
    List(
      criteriaPowerPlantType.map(powerPlantTable.powerPlantType === _),
      criteriaOrgName.map(powerPlantTable.orgName like s"%${criteriaOrgName}%") // fails to compile here!
    ).collect({case Some(criteria)  => criteria}).reduceLeftOption(_ && _)
  }

Есть ли что-то встроенное в Slick для этого?


person joesan    schedule 06.09.2017    source источник


Ответы (1)


Вот к чему я пришел, и это работает, но не уверен, что это эффективно:

def powerPlantsFor(criteriaPowerPlantType: Option[PowerPlantType], criteriaOrgName: Option[String], onlyActive: Boolean) = {
  val query = for {
    filtered <- all.filter(f =>
      criteriaPowerPlantType.map(d =>
        f.powerPlantType === d).getOrElse(slick.lifted.LiteralColumn(true)) &&
        criteriaOrgName.map(a =>
          f.orgName like s"%$a%").getOrElse(slick.lifted.LiteralColumn(true))
    )
  } yield filtered

  query.filter(_.isActive === onlyActive)
}

Но когда я изучаю сгенерированный SQL-запрос, я вижу, что в базе данных выполняются два оператора, как показано ниже:

[debug] s.j.J.statement - Preparing statement: select `powerPlantId`, `orgName`, `isActive`, `minPower`, `maxPower`, `rampRate`, `rampRateSecs`, `powerPlantType`, `createdAt`, `updatedAt` from `powerPlant` where (true and (`orgName` like '%Organization-%')) and (`isActive` = true) limit 0,5
[debug] s.j.J.statement - Preparing statement: select `powerPlantId`, `orgName`, `isActive`, `minPower`, `maxPower`, `rampRate`, `rampRateSecs`, `powerPlantType`, `createdAt`, `updatedAt` from `powerPlant` where `isActive` = true

Как это оптимизировать?

person joesan    schedule 06.09.2017