You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Slick过滤Rep[Seq[T]]:Play! Scala项目jsonb数组查询问题

嘿,刚好碰到过类似的场景,给你分享个高效的解法,不用再挨个遍历test2的元素啦~

解决Slick查询PostgreSQL jsonb数组中满足条件的行

首先得明确:PostgreSQL本身对jsonb有很强的原生支持,咱们不用在代码里手动遍历数组元素,直接让数据库帮咱们做过滤,既简洁又高效。

核心思路

你的需求是筛选config->test2数组中至少有一个元素的bool字段为true的行,PostgreSQL提供了两种靠谱的实现方式:

  1. 使用jsonb_path_exists路径查询(PostgreSQL 12+支持,最简洁)
  2. 结合jsonb_array_elements展开数组做子查询(兼容旧版本PostgreSQL)

下面结合Slick来具体实现:

前提假设

假设你的表定义大概是这样(基于Play的Json类型,搭配Slick的PostgreSQL支持):

import play.api.libs.json.Json
import slick.jdbc.PostgresProfile.api._

case class YourEntity(id: Long, config: Json)
class YourTable(tag: Tag) extends Table[YourEntity](tag, "your_table") {
  def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
  def config = column[Json]("config") // Play-Slick通常会自动处理Json与jsonb的隐式映射
  def * = (id, config) <> (YourEntity.tupled, YourEntity.unapply)
}

val yourTableQuery = TableQuery[YourTable]

方法1:用jsonb_path_exists(推荐)

这个方法直接用PostgreSQL的JSON路径表达式,一行就能搞定过滤,而且数据库可以利用jsonb索引(如果你创建了的话):

val filterQuery = yourTableQuery.filter { row =>
  // 自定义Slick表达式,生成jsonb_path_exists的SQL语句
  SimpleExpression.bool[Json](
    (configCol, queryBuilder) => {
      queryBuilder += "jsonb_path_exists("
      queryBuilder.expr(configCol)
      queryBuilder += ", '$.test2[*].bool ? (@ == true)')"
    }
  ).apply(row.config)
}

// 执行查询(db是你的Slick Database实例)
val result: Future[Seq[YourEntity]] = db.run(filterQuery.result)

这里的路径表达式$.test2[*].bool ? (@ == true)意思是:遍历test2数组的所有元素,检查是否存在元素的bool字段等于true。

方法2:用jsonb_array_elements子查询(兼容旧版PG)

如果你的PostgreSQL版本低于12,用这种方式更稳妥:

val filterQuery = yourTableQuery.filter { row =>
  // 子查询:展开test2数组,检查是否有元素的bool为true
  exists(
    sql"""SELECT 1 FROM jsonb_array_elements(${row.config}->'test2') elem WHERE elem->>'bool' = 'true'"""
      .as[Int]
      .take(1)
  )
}

这个子查询会把test2数组展开成多行,只要有一行满足bool='true',就会返回1,外层的exists就会判定为true,从而筛选出目标行。

为什么不要挨个遍历元素?

你之前尝试的逐个检查test2[0]、test2[1]...有三个明显的问题:

  • 代码冗余:test2有10个元素就要写10个OR条件,维护起来太麻烦
  • 扩展性差:如果以后test2的元素数量变化,代码就得跟着修改
  • 效率低:数据库要逐个检查每个元素,而上面的两种方法都是数据库优化过的,尤其是路径查询可以利用jsonb索引,查询速度快很多

额外优化:给jsonb列建索引

如果这个查询很频繁,建议给config列建个jsonb路径索引,进一步提升查询速度:

CREATE INDEX idx_config_test2_bool ON your_table USING gin (config jsonb_path_ops);

内容的提问来源于stack exchange,提问作者Scaum

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:14:19