根据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)
对于那些想要做类似事情的人,我将语法切换为更详细的
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))
}