## 模板参数可模糊查询(±容差)功能需求文档 ### 1. 背景与目标 当前用户端「按模板参数查询」要求参数值与数据库完全相同才能命中,实际使用中数值类参数(如内径、外径、长度等)存在测量/录入微小误差,严格等值导致命中率偏低。新增能力:在管理端创建模板时,为每个参数提供「可模糊查询」选项;开启后,用户搜索该参数时按数值区间匹配(±容差);未开启的参数继续精确等值。 ### 2. 业务范围 - 场景:用户端/管理端的商品列表查询(含「按模板参数查询」模式)。 - 对象:模板参数定义(仅限数值型参数生效)。 - 不影响:名称/品牌/型号/规格关键字搜索逻辑;非数值类型参数的等值匹配逻辑。 ### 3. 术语与约束 - 模板参数类型:string/number/boolean/enum/date。 - 模糊查询仅对 type=number 生效;其他类型不展示该选项或忽略配置。 - 容差(tolerance):对搜索入参 v,匹配区间为 \[v - tolerance, v + tolerance](闭区间)。默认容差为 1(见配置项),可在参数层级单独覆盖。 - 组合关系:多参数为 AND 关系;每个参数根据其「可模糊查询」与容差独立计算。 ### 4. 交互与流程 - 管理端-模板配置: - 新建/编辑模板参数时,新增选项: - 可模糊查询(开关,仅当类型为 number 显示) - 容差值(number,>0,显示单位提示,同 `unit` 字段;当开关开启时必填,否则置空) - 校验: - type≠number 时禁止开启; - 容差必须为正数,支持小数; - 可保存为“使用平台默认容差”,当字段留空时后端落默认(见配置)。 - 用户端/管理端-按模板参数查询: - 入参与现状一致:仍以 `templateId` + 多个 `param_*` 传参; - 行为变化: - 对应参数若开启可模糊查询:按区间 \[v - tol, v + tol] 比较; - 否则:仍为精确等值比较。 ### 5. 数据模型变更(待实施) - 表:`part_template_params` - 新增列: - `fuzzy_searchable` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否允许模糊查询(仅数值型)' - `fuzzy_tolerance` DECIMAL(18,6) NULL COMMENT '容差;NULL 表示使用平台默认容差' - 说明: - 仅当 `type='number' AND fuzzy_searchable=1` 时才使用容差; - 初始迁移将全部历史记录置为 `fuzzy_searchable=0, fuzzy_tolerance=NULL`,保持现有行为不变。 ### 6. 配置项(后端) - `search.fuzzy.enabled`(bool,默认 true):是否启用模糊查询全局开关; - `search.fuzzy.defaultTolerance`(decimal,默认 1.0):当参数未设置 `fuzzy_tolerance` 时使用; - 读取途径:Spring 配置(application.properties/yaml)或环境变量。禁止在代码中硬编码数字 1。 - 仅全局配置,不支持租户级(`system_parameters`)覆盖;无需设置小数精度上限/最大容差限制。 ### 7. 接口协议与兼容性 - 查询接口:`GET /api/products`(已存在) - 入参保持不变:`templateId`、`param_*`。 - 语义扩展(无须 `templateId` 也启用模糊):后端将基于商品行的 `template_id` 与参数定义逐行判定某个 `param_*` 是否启用 ±容差;若该参数在对应模板中未开启模糊或非数值型,则对该条件执行等值匹配。 - 模板接口:`POST /api/admin/part-templates`、`PUT /api/admin/part-templates/{id}`(已存在) - 参数定义对象新增字段: - `fuzzySearchable`(boolean) - `fuzzyTolerance`(number,nullable) - 若前端暂未改造,后端默认按 `fuzzySearchable=false` 处理,兼容旧请求体。 (根据「接口规范生效条件」,待功能开发完成后更新 `doc/openapi.yaml` 中对应 schema 与描述,并在 summary/description 标注实现状态) ### 8. 后端实现要点(建议方案) 当前实现(精确匹配),示意: ```sql -- 现状(等值): AND JSON_UNQUOTE(JSON_EXTRACT(p.attributes_json, '$.内径')) = '10' ``` 推荐实现: - 行级判定方案(支持无 `templateId` 也启用模糊): - 对每个传入的 `param_=v`: - 以 `EXISTS` 子查询或 `JOIN part_template_params ptp ON ptp.template_id=p.template_id AND ptp.field_key=''` 获取参数定义; - 若 `ptp.type='number' AND ptp.fuzzy_searchable=1`:对 `v` 解析为数值,计算 `tol = COALESCE(ptp.fuzzy_tolerance, :defaultTolerance)`; - 下限截断:`lower = GREATEST(0, v - tol)`; - 条件: ```sql CAST(JSON_UNQUOTE(JSON_EXTRACT(p.attributes_json, '$.')) AS DECIMAL(18,6)) BETWEEN :lower AND :upper ``` - 否则:执行等值匹配: ```sql JSON_UNQUOTE(JSON_EXTRACT(p.attributes_json, '$.')) = :val ``` - 快路径(可选):当请求携带 `templateId` 时,可先一次性加载该模板参数定义映射到内存,按映射决定每个条件构造,以减少 `JOIN/EXISTS` 次数。 - 容差取值:优先 `ptp.fuzzy_tolerance`,否则全局 `search.fuzzy.defaultTolerance`。 性能建议: - 初期:允许全表扫描 + JSON_EXTRACT;观察真实 QPS 与延迟; - 进阶(可选):对热点参数引入“生成列 + 索引”(Generated Column),例如: - 在 `products` 增加 `attr_ DECIMAL(18,6) GENERATED ALWAYS AS (CAST(JSON_UNQUOTE(JSON_EXTRACT(attributes_json, '$.')) AS DECIMAL(18,6))) STORED` 并建索引,以支持范围查询; - 仅对访问量高的少数参数启用,避免列爆炸。 ### 9. 管理端实现要点(UI/校验) - `admin/src/views/parts/Templates.vue`: - 参数编辑行新增: - 开关:可模糊查询(仅 type=number 显示) - 数值输入:容差(显示单位,>0,支持小数;留空表示使用平台默认) - 保存/加载兼容:与后端新增字段映射,历史数据默认显示为关闭态。 - 校验:当参数开启模糊时,对应值在 UI 侧仅允许数字输入;单位提示与 `unit` 一致。 ### 10. 验收标准(Test Cases) - 单参数-模糊:模板字段 `内径`(number,fuzzy=true,tolerance=1);商品 A/B/C 分别取值 9/10/11;搜索 `param_内径=10` 命中 A/B/C。 - 单参数-精确:同上但 fuzzy=false;搜索 `param_内径=10` 仅命中 B。 - 多参数组合:`内径`(fuzzy=true, tol=0.5)、`长度`(fuzzy=false);搜索 `param_内径=10`、`param_长度=20` 仅命中满足区间与等值的交集。 - 无 templateId:也启用模糊;后端逐行按 `p.template_id` 与参数定义判定是否应用容差。 - 容差来源:当 `fuzzy_tolerance=NULL` 时,生效平台默认容差;覆盖值生效优先级高于默认。 - 非数值参数:即使请求携带 `param_颜色=黑`,也严格等值。 - 下限截断:当 `v - tol < 0` 时,以 `0` 作为下限;不支持负数参数匹配。 - 非法输入:当参数在模板中开启模糊但请求值非数字时,返回 400(Bad Request)。 ### 11. 兼容与回退 - 不改动现有请求入参与返回体,历史客户端无需升级亦可按原精确逻辑使用; - 新能力由模板参数配置显式开启,可随时在模板中关闭; - 如需全局关闭,可通过 `search.fuzzy.enabled=false` 临时禁用(后端配置)。 ### 12. 风险与注意事项 - 数据质量:历史 `attributes_json` 中数值可能以字符串存储;需统一以 `CAST(JSON_UNQUOTE(...))` 解析。 - 单位与容差:UI 需提示单位;容差与单位一一对应,避免“毫米 vs 厘米”误解。 - 性能:范围查询较等值更难走索引;必要时引入“生成列+索引”优化热点字段。 - 负数与边界:不支持负数参数;区间采用闭区间,且下限截断为 `0`。 ### 13. 实施清单(参考) 1) 数据库:为 `part_template_params` 增列 `fuzzy_searchable`、`fuzzy_tolerance`;(变更需通过 MysqlMCP,成功后同步更新 `doc/database_documentation.md` 与 `backend/db/db.sql`) 2) 配置:新增 `search.fuzzy.*` 配置项并给出默认值(全局生效,无租户级覆盖); 3) 管理端:模板参数编辑 UI 新增开关与容差输入; 4) 后端:按 8 节改造查询 SQL 构建逻辑(无 `templateId` 也启用模糊,行级按模板判定); 5) 文档:在功能开发完成后更新 `doc/openapi.yaml` 中模板参数 schema 与 `GET /api/products` 的查询规则说明,并标注实现状态; 6) 发布:前后端同步上线;无需灰度与回滚开关; 7) 验收:按 10 节用例覆盖单测/集成测试与手工回归。