罗展丰
Published on 2026-03-05 / 17 Visits
0
0

自定义查询条件

一、背景

在日常业务开发过程中,传统接口的查询条件、排序规则等参数均为硬编码实现,参数格式和查询逻辑固定,仅能满足预设的业务场景。当客户需要调整查询条件(如修改字段筛选范围、新增筛选维度、调整排序方式)时,必须由开发人员修改代码、重新测试并发布版本,导致:

  1. 客户需求响应周期长,灵活性极低;
  2. 开发人员重复编写相似的查询接口,效率低下;
  3. 接口版本迭代频繁,维护成本高。

为解决上述问题,设计并实现通用灵活查询接口,支持客户通过标准化 JSON 参数自定义查询条件、排序规则,无需修改代码即可满足多样化的查询需求。

二、核心实现逻辑

2.1 整体设计思路

通用灵活查询接口的核心是将结构化的 JSON 查询参数动态解析为可执行的 SQL 语句,整体逻辑分为三层:

  1. 参数接收层:接收前端传入的标准化 JSON 参数,完成参数格式校验和结构化转换;
  2. SQL 解析层:递归解析 JSON 中的筛选条件和排序规则,将其转换为 SQL 的 WHERE子句和 ORDER BY子句;
  3. 执行层:对解析后的 SQL 执行并返回查询结果。

2.2 核心解析逻辑

(1)筛选条件解析逻辑

  • 支持嵌套条件:外层条件和内层条件均通过 joiner定义连接关系,递归解析所有层级的条件;
  • 支持多操作符:将 JSON 中的 operator映射为 SQL 的比较运算符(如 >=in等);
  • 支持多值条件:将 conditionValues数组适配不同操作符的参数格式(单值取第一个元素,多值拼接为 (val1, val2))。

(2)排序规则解析逻辑

  • sortName匹配数据库表字段,按 sortDirection确定排序方向;
  • 支持多字段排序,多个排序规则按数组顺序拼接为 ORDER BY 字段1 方向1, 字段2 方向2

三、传参格式详细解释

3.1 示例参数解读

构建条件

(id >= 100 and id <= 1000) and (createTime >= "2025-7-1 12:00:00" and createTime <= "2025-8-1 12:00:00")

输入 JSON 参数

json

{
	"filter": {
		"joiner": "and",
		"conditions": [{
			"joiner": "and",
			"conditions": [{
				"conditionName": "id",
				"operator": ">=",
				"conditionValues": ["100"]
			}, {
				"conditionName": "id",
				"operator": "<=",
				"conditionValues": ["1000"]
			}]
		}, {
			"joiner": "and",
			"conditions": [{
				"conditionName": "createTime",
				"operator": ">=",
				"conditionValues": ["2025-7-1 00:00:00"]
			}, {
				"conditionName": "createTime",
				"operator": "<=",
				"conditionValues": ["2025-8-1 00:00:00"]
			}]
		}]
	},
	"sorts": [{
		"sortName": "createTime",
		"sortDirection": "desc"
	}]
}

解析逻辑说明

  1. filter.joiner = "and":表示根层级的两个子条件(id 区间、时间区间)需同时满足;
  2. 第一个子条件(filter.conditions[0]):joiner = "and",表示 id >= 100id <= 1000
  3. 第二个子条件(filter.conditions[1]):joiner = "and",表示 createTime >= '2025-7-1 00:00:00'createTime <= '2025-8-1 00:00:00'
  4. sorts[0].sortName = "createTime" + sortDirection = "desc":表示按 createTime降序排序。

3.2 核心参数路径与说明

参数路径 类型 必选 说明
filter Object 筛选条件的根容器,所有筛选规则均包含在此节点下
filter.joiner String 根层级子条件的连接符,仅支持 and/or,表示所有子条件的组合关系
filter.conditions Array 根层级的子条件列表,元素可为嵌套的 filter对象或原子条件对象
filter.conditions[*].joiner String 是(元素为 filter 时) 嵌套层级子条件的连接符,仅支持 and/or
filter.conditions[*].conditions Array 是(元素为 filter 时) 嵌套层级的子条件列表
filter.conditions[*].conditionName String 是(元素为原子条件时) 筛选字段名,需与数据库表字段名完全一致(如 idcreateTime
filter.conditions[*].operator String 是(元素为原子条件时) 筛选操作符,支持 >=/<=/=/!=/like/in/not in
filter.conditions[*].conditionValues Array 是(元素为原子条件时) 筛选值数组:1. 单值操作符(如 >=)取数组第一个元素;2. 多值操作符(如 in)取数组所有元素
sorts Array 排序规则列表,无此节点时不排序
sorts[*].sortName String 是(sorts 非空时) 排序字段名,需与数据库表字段名完全一致
sorts[*].sortDirection 排序方向,默认 asc(升序),支持 desc(降序)

四、使用场景

  1. 客户自助调整查询条件:如运营人员需要灵活筛选不同时间范围、ID 区间的订单 / 用户数据,无需开发介入;
  2. 多维度查询:报表系统需要支持用户自定义筛选维度(如按地区、时间、状态组合筛选)和排序方式;
  3. 临时数据导出需求:业务人员临时需要导出特定条件的数据,通过该接口快速获取,无需开发定制接口;
  4. 第三方系统对接:对接外部系统时,对方需自定义查询条件,通用接口可满足多样化的对接需求。

五、风险点与防控措施

风险类型 具体风险 防控措施
SQL 注入 恶意传入表名、字段名、操作符或值,构造注入语句 1. 表名做白名单校验,仅允许查询指定表;
2. 字段名校验,仅允许查询表中存在的字段;
3. 操作符白名单(仅允许预设的 >=、<= 等);
4. 参数值使用占位符,避免直接拼接;
5. 限制接口访问权限,仅授权用户可调用
性能风险 复杂嵌套条件、大范围数据查询导致数据库慢查询 1. 限制单次查询返回条数(如默认最多 1000 条);
2. 对查询字段增加索引;
3. 记录慢查询日志,监控异常查询;
4. 禁止使用 like '% xxx' 等低效查询(可选)
数据安全 未授权用户查询敏感数据 1. 接口增加身份认证和权限校验;
2. 按用户权限过滤数据(如普通用户仅能查询自己的数据);
3. 敏感字段(如手机号、身份证)脱敏返回;
4. 记录接口调用日志,审计操作行为
参数格式错误 字段名错误、操作符不支持、值类型不匹配 1. 入参时校验字段名是否存在、操作符是否合法;2. 对时间、数字等字段做类型转换校验;3. 返回清晰的错误提示(如 “字段 createTime 不存在”)
嵌套层级过深 条件嵌套层级过多导致 SQL 解析异常 1. 限制条件嵌套最大层级(如最多 3 层);2. 解析 SQL 时增加异常捕获,返回友好提示

六、参数到 SQL 的转换效果

6.1 转换规则

  1. 筛选条件:JSON 中的嵌套条件 → SQL 的 WHERE子句(括号区分嵌套层级);
  2. 排序规则:JSON 中的 sorts数组 → SQL 的 ORDER BY子句;
  3. 最终 SQL:拼接 SELECT * FROM 目标表 + WHERE子句 + ORDER BY子句(目标表通过接口参数指定)。

6.2 示例转换效果

扩展示例

若 JSON 参数调整为多值 in查询 +or连接:

json

{
	"filter": {
		"joiner": "or",
		"conditions": [{
			"conditionName": "id",
			"operator": "in",
			"conditionValues": ["100", "200", "300"]
		}, {
			"conditionName": "status",
			"operator": "=",
			"conditionValues": ["1"]
		}]
	},
	"sorts": [{
		"sortName": "id",
		"sortDirection": "asc"
	}]
}

转换后的 SQL:

sql

SELECT * FROM user 
WHERE id IN ('100', '200', '300') OR status = '1'
ORDER BY id ASC;

七、总结

  1. 核心逻辑:通用灵活查询接口的核心是将标准化 JSON 参数递归解析为 SQL 的 WHERE 子句和 ORDER BY 子句,实现查询条件的动态配置;
  2. 参数规范:关键参数路径(如 filter.joinerfilter.conditions[*].conditionName)需严格匹配数据库字段和预设规则,确保解析正确;
  3. 风险防控:接口安全的核心是防范 SQL 注入、控制查询性能、保障数据安全,需通过白名单、权限校验、参数校验等手段落地。

Comment