Slick 3.0 Menggunakan Filter untuk Mengkueri data

Saya memiliki kelas kasus seperti di bawah ini:

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

Pemetaan Tabel saya terlihat seperti ini:

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)
    }
  }

Saya ingin membuka filter dan mengisi kueri dinamis! Selain itu, saya ingin menggunakan pernyataan seperti dalam tipe SQL untuk String yang saya hasilkan.

Jadi dalam kasus saya di atas, nama org di PowerPlantFilter saya harus diperiksa keberadaannya dan jika ya, itu akan menghasilkan pernyataan serupa di SQL yang dihasilkan!

Ini adalah percobaan pertama saya, tapi jelas ini gagal!

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(_ && _)
  }

Apakah ada sesuatu yang dibangun di Slick untuk melakukan ini?


person joesan    schedule 06.09.2017    source sumber


Jawaban (1)


Inilah yang saya dapatkan dan berhasil, tetapi tidak yakin apakah ini efisien:

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)
}

Tetapi ketika saya memeriksa kueri SQL yang dihasilkan, saya melihat dua pernyataan dieksekusi pada database yaitu seperti di bawah ini:

[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

Bagaimana cara mengoptimalkan ini?

person joesan    schedule 06.09.2017