PostgreSQL JSON列IN查询问题:FastAPI中无法过滤数据求助
解决PostgreSQL JSON字段多列表过滤查询问题
原代码存在两个核心问题导致查询失效:
- 参数匹配错误:你把每个筛选列表作为元组的独立元素传给
execute,但数据库驱动需要将所有筛选值展开为扁平的一维参数列表,否则占位符%s和实际参数无法一一对应。 - 空列表引发语法错误:如果某个字段的筛选列表为空(比如
data.category是空列表),会生成IN ()这种PostgreSQL不支持的无效语法。
以下是修复后的可用代码:
# 整理筛选规则与对应参数 filter_conditions = [] params = [] # 建立JSON字段与筛选列表的映射关系 filter_mapping = [ ('category', data.category), ('domain', data.domain), ('technology', data.technology), ('topic', data.topic), ('author', data.author), ('platform', data.platform), ('processerfamily', data.processerfamily), ('processortype', data.processortype), ('embeddedboard', data.embeddedboard), ] for field_name, values in filter_mapping: if values: # 仅处理非空的筛选列表 # 生成对应数量的占位符 placeholders = ', '.join(['%s'] * len(values)) # 添加当前字段的筛选条件 filter_conditions.append(f'(\"Tags\" ->> \'{field_name}\') IN ({placeholders})') # 将筛选值扁平化加入参数列表 params.extend(values) # 构建并执行SQL if filter_conditions: where_clause = ' OR '.join(filter_conditions) sql = f""" SELECT * FROM demo_data.demo_assets WHERE {where_clause}; """ await cur.execute(sql, params) results = await cur.fetchall() else: # 若所有筛选列表为空,返回全量数据(可根据需求调整逻辑) await cur.execute("SELECT * FROM demo_data.demo_assets;") results = await cur.fetchall()
关键修复说明
- 动态生成条件:只对非空列表生成
IN子句,彻底避免空列表导致的语法错误。 - 扁平化参数:用
params.extend(values)将每个列表的元素逐个加入参数列表,确保每个%s都对应一个具体值。 - 安全拼接SQL:仅拼接字段名和占位符,实际筛选值通过参数传递,完全规避SQL注入风险。
如果你使用的是
asyncpg驱动,占位符需要改为带编号的$1, $2...,可调整占位符生成逻辑:current_idx = 1 for field_name, values in filter_mapping: if values: placeholders = ', '.join([f'${current_idx + i}' for i in range(len(values))]) filter_conditions.append(f'(\"Tags\" ->> \'{field_name}\') IN ({placeholders})') params.extend(values) current_idx += len(values)
内容的提问来源于stack exchange,提问作者Karan N
相关产品推荐
相关产品推荐

