Flask SQLAlchemy如何筛选Postgres JSON列表字段含指定字符串的记录
问题原因
你遇到的报错是因为SQLAlchemy原生的contains运算符并没有针对通用JSON类型实现对应的列表包含逻辑,不同数据库对JSON字段的查询语法存在差异,需要结合对应数据库的原生语法来实现需求。
可行实现方案
方案1:适配PostgreSQL数据库
如果你使用PostgreSQL作为底层数据库,推荐直接将字段改为JSONB类型(查询性能和功能支持更完善),如果要保留原JSON类型,写法如下:
from sqlalchemy import cast, JSONB Testing.query.filter( cast(Testing.alias, JSONB).contains([url_param_val]) ).all()
也可以直接调用PG原生的@>包含运算符实现:
Testing.query.filter( Testing.alias.op('@>')([url_param_val]) ).all()
方案2:适配MySQL数据库
MySQL可以通过内置的JSON_CONTAINS函数实现查询,搭配json_quote自动处理参数格式,同时避免SQL注入风险:
from sqlalchemy import func Testing.query.filter( func.json_contains(Testing.alias, func.json_quote(url_param_val)) ).all()
方案3:全数据库兼容兜底方案
如果你需要兼容多种数据库,或者业务数据量很小,可以先全量查询后在Python层过滤:
all_records = Testing.query.all() matched_records = [record for record in all_records if url_param_val in record.alias]
优化建议
如果你的业务场景经常需要对alias字段做包含查询,更推荐将字段类型改为数据库原生的ARRAY类型,原生数组类型的contains运算符是全数据库兼容的,查询性能也远高于JSON类型的查询:
# 修改模型字段定义 alias = db.Column(db.ARRAY(db.String(25))) # 修改后你原来的写法就可以直接生效 Testing.query.filter(Testing.alias.contains(url_param_val)).all()
内容的提问来源于stack exchange,提问作者yoyoyoyo123
相关产品推荐
相关产品推荐

