slick-pg 使用特定的 array_length 按列过滤行

问题描述 投票:0回答:1

根据https://www.postgresql.org/docs/8.4/functions-array.html,有一个

array_length
PG Oper/Function.
然后,根据https://github.com/tminglei/slick -pg/tree/master/core/src/main/scala/com/github/tminglei/slickpg/array,我可以看到有记录表明存在一个
Slick Oper/Function,.
我一直在浏览文档和各种帖子。但是,我似乎无法将如何在类似于以下的查询中利用此
PG Oper/Function
联系起来:

    import DatabaseObjects.profile.api._
    val randomFunction: Rep[Double] = SimpleFunction.nullary[Double]("random")
    val query: Query[GeneratorV1, GeneratorV1Row, Seq] = GeneratorV1
      .sortBy(_ => randomFunction)
      .filter(_.rasterizationJobConfig +>> "activity" === activityTypeEnum)
      .filter(_.jobStatus === GeneratorStatuses.success)
      .take(N)

我需要更改此查询以添加最后一个过滤器。下面是修改后的查询,其中包含附加

array_length
过滤器的伪代码。如以下 SQL 查询所示:

SELECT * from generator_v1 WHERE rasterization_job_config->>'activity' = 'PLANTING'
  AND job_status = 'success' AND array_length(worker_job_ids, 1) = 2 LIMIT 5;
    import DatabaseObjects.profile.api._
    val randomFunction: Rep[Double] = SimpleFunction.nullary[Double]("random")
    val query: Query[GeneratorV1, GeneratorV1Row, Seq] = GeneratorV1
      .sortBy(_ => randomFunction)
      .filter(_.rasterizationJobConfig +>> "activity" === activityTypeEnum)
      .filter(_.jobStatus === GeneratorStatuses.success)
      .filter(/* pseudo-code */ _.jobIds.array_length > 0 && _.jobIds.array_length < N)
      .take(N)

到目前为止,我已经尝试过:

    import DatabaseObjects.profile.api._
    val randomFunction: Rep[Double] = SimpleFunction.nullary[Double]("random")

    def arrayLength(rep: Rep[List[Long]]): Rep[Boolean] = {
      val expression = SimpleExpression.unary[List[Long], Boolean] { (s, queryBuilder) =>
        queryBuilder.sqlBuilder += "array_length("
        queryBuilder.expr(s)
        queryBuilder.sqlBuilder += ", 1) = 2"
      }
      expression.apply(rep)
    }

    val query: Query[GeneratorV1, GeneratorV1Row, Seq] = GeneratorV1
      .sortBy(_ => randomFunction)
      .filter(_.rasterizationJobConfig +>> "activity" === activityTypeEnum)
      .filter(_.jobStatus === GeneratorStatuses.success)
      .filter(row => (row.workerJobIds, arrayLength(row.workerJobIds)))
      .take(N)
scala slick slick-pg
1个回答
0
投票

对于那些想要做类似事情的人,我将语法切换为更详细的

yield
语句,然后使用上面的 SimpleExression:

  def getNGeneratorV1RowsForAgronomicActivity(N: Int,
                                              maxJobs: Int,
                                              database: Database,
                                              activityTypeEnum: ActivityTypeEnum
  ): Seq[GeneratorV1Row] = {
    import DatabaseObjects.profile.api._

    def arrayLength(rep: Rep[List[Long]]): Rep[Boolean] = {
      val expression = SimpleExpression.unary[List[Long], Boolean] {
        (s, q: JdbcStatementBuilderComponent#QueryBuilder) =>
          val _ = q.sqlBuilder += "array_length("
          q.expr(s)
          val _ = q.sqlBuilder += s", 1) = $maxJobs"
          ()
      }
      expression.apply(rep)
    }

    val randomFunction: Rep[Double] = SimpleFunction.nullary[Double]("random")

    val query: Query[
      (
        Rep[Long],
        Rep[UUID],
        Rep[LocalDateTime],
        Rep[GeneratorStatus],
        Rep[List[Long]],
        Rep[Option[JsValue]],
        Rep[Option[JsValue]]
      ),
      (Long, UUID, LocalDateTime, GeneratorStatus, List[Long], Option[JsValue], Option[JsValue]),
      Seq
    ] =
      for (
        generatorV1Row <- GeneratorV1
          .sortBy(_ => randomFunction)
          .filter(row => row.rasterizationJobConfig +>> "activity" === activityTypeEnum)
          .filter(row => row.jobStatus === GeneratorStatuses.success)
          .filter(row => arrayLength(row.workerJobIds))
          .take(N)
      )
        yield (
          generatorV1Row.id,
          generatorV1Row.jobId,
          generatorV1Row.timeReceived,
          generatorV1Row.jobStatus,
          generatorV1Row.workerJobIds,
          generatorV1Row.pyroRasterizationConfig,
          generatorV1Row.rasterizationJobConfig
        )

    val crap = query
    print(crap.toString)

    DatabaseModule
      .wait(database.run(query.result))
      .map(tuple => GeneratorV1Row(tuple._1, tuple._2, tuple._3, tuple._4, tuple._5, tuple._6, tuple._7))
  }
© www.soinside.com 2019 - 2024. All rights reserved.