能否用SQLAlchemy结合LIKE查询JSONB列表中的值?
在SQLAlchemy中对JSONB数组进行类LIKE的模糊查询
嘿,这个需求我之前刚好碰到过!SQLAlchemy本身没有直接提供像contains_like('%app%')这种一键式的方法,但结合PostgreSQL的原生JSONB函数,完全能实现你要的效果——检查JSONB数组里是否存在包含指定子串的元素。
下面给你两种实用的实现方式,根据你的PostgreSQL版本选就行:
方法1:展开数组后匹配(兼容所有支持JSONB的PostgreSQL版本)
这种方法的思路是把JSONB数组拆成单个元素,对每个元素做文本模糊匹配,最后去重得到符合条件的行:
from sqlalchemy import select, func from your_models import Basket # 替换成你实际的模型类 # 构建查询语句 query = select(Basket).distinct().where( # 把fruits数组展开成单个元素,转成文本后做LIKE匹配 func.jsonb_array_elements(Basket.fruits).astext.like("%app%") ) # 执行查询获取结果 results = db_session.execute(query).scalars().all()
这里的jsonb_array_elements是PostgreSQL的原生函数,负责把JSONB数组拆成多行;.astext用来把JSONB类型的元素转换成文本,这样才能用like做模糊匹配;distinct()是为了避免因为数组展开成多行后,同一行数据被多次返回。
方法2:用JSON路径查询(PostgreSQL 12+推荐)
如果你的PostgreSQL版本是12或更高,用JSON路径查询会更简洁高效:
from sqlalchemy import select, func, text from your_models import Basket query = select(Basket).where( func.jsonb_path_query_exists( Basket.fruits, # JSON路径表达式:检查数组中是否有元素包含"app"子串 text('$[*] ? (@ like "%app%")') ) ) results = db_session.execute(query).scalars().all()
解释一下路径表达式:$[*]表示匹配数组中的所有元素,@ like "%app%"表示当前元素要满足包含"app"的模糊匹配条件。jsonb_path_query_exists会直接返回布尔值,判断是否存在符合条件的元素,不需要额外去重。
最后提醒下:这两种方法都依赖PostgreSQL的JSONB特性,如果你的数据库不是PostgreSQL,可能需要换成对应数据库的JSON处理函数,但核心思路是一致的——要么展开数组匹配,要么用路径查询做批量检查。
内容的提问来源于stack exchange,提问作者john
相关产品推荐
相关产品推荐

