fix: 第16轮搜索审计修复 — all_not/group_negated分离 + _parse_primary重复组 + 错误显示
- Bug 2 (MEDIUM): all_not 混淆外部NOT与内部NOT,新增 group_negated 字段区分,_pubmed_conditions 改用 pp.group_negated[idx] 替代 all_not - Bug 1 (MEDIUM): _parse_primary 括号组内重复group赋值,只处理 group_id < 0 的未分配terms,_parse_or_expr 增加 depth>0 守卫 - Bug 3 (MEDIUM): SearchView.vue 搜索错误显示为"no results", 新增 searchError ref + NResult 错误面板 - Bug 4 (LOW): literature.py UUID类型转换优化
This commit is contained in:
@@ -1207,6 +1207,52 @@
|
||||
|
||||
---
|
||||
|
||||
## 第十六轮:第 16 轮审计修复(4 项修复 + 3 项记录)
|
||||
|
||||
**日期**:2026-07-29
|
||||
**提交**:`(待推送)`
|
||||
**数量**:4 项修复 + 3 项记录
|
||||
**触发**:用户第 11 次要求全面检查(Round 16,3 并行 agent:Normal 搜索边缘、前端参数、NOT 检测)
|
||||
**测试**:1007 全部通过 + 前端 build 通过
|
||||
|
||||
### Bug-1 (MEDIUM): `_parse_primary` 括号组内重复 group 赋值
|
||||
|
||||
- **文件**:`pubmed_query_parser.py:706-709`
|
||||
- **根因**:`_parse_or_expr` 在 `A OR B AND C` 时为 `[B, C]` 创建 sub-group。随后 `_parse_primary` 将所有 terms(含已 sub-group 的)再统一加到 parent group。sub-group 内的 term 同时出现在两个 group → `_pubmed_conditions` 遍历 group 列表时为其生成两套条件 → SQL 中产生重复/多余的过滤条件,静默排除合法结果
|
||||
- **影响**:`NOT (A OR B AND C)` 类带 sub-group 的括号组查询可能返回零结果
|
||||
- **修复**:`_parse_primary` 只从 `t.group_id < 0`(未分配)的 term 创建 parent group。sub-group 已分配的不再加入。同时增加 depth 守卫:`_parse_or_expr` 在 `self._depth > 0`(括号内)时直接 flat 返回,不创建 sub-group
|
||||
|
||||
### Bug-2 (MEDIUM): `all_not` 混淆外部 NOT 与内部 NOT
|
||||
|
||||
- **文件**:`search_engine.py:1134-1172`
|
||||
- **根因**:`all_not = all(t.is_not for t in group)` 无法区分 `NOT (A OR B)`(外部 NOT:应生成 `not_(or_(A, B))`) 和 `(NOT A OR NOT B)`(内部 NOT:应生成 `or_(not_(A), not_(B))`)。两者都 `all_not=True`,但语义完全不同
|
||||
- **修复**:
|
||||
- 解析器端:新增 `ParsedPubmedQuery.group_negated: list[bool]` 字段,`_parse_primary` 在创建 parent group 时记录是否为外部 NOT wrapper
|
||||
- 引擎端:用 `group_negated[idx]` 替代 `all_not`,外部 NOT 走 `not_(combine_fn(g_neg))`,内部 NOT 走 `combine_fn(g_pos + g_neg_with_not_)`
|
||||
- **验证**:`NOT (A OR B)` 与 `(NOT A OR NOT B)` 生成不同的 SQL 条件组合
|
||||
|
||||
### Bug-3 (MEDIUM): 搜索错误显示为"no results"
|
||||
|
||||
- **文件**:`SearchView.vue:365-367`
|
||||
- **根因**:catch 块只调用 `toast.apiError()`(瞬态通知提示),但 `results = []` 导致 `<NEmpty>` 显示"未找到匹配文献",用户以为搜索有结果只是条件过严,实际是后端错误
|
||||
- **修复**:新增 `searchError` ref,catch 时设置明确错误信息,模板条件渲染 `<NResult>` 错误面板替代 `NEmpty`。成功搜索时清除 `searchError`
|
||||
|
||||
### Bug-4 (LOW): UUID 类型转换在中文标签子查询中
|
||||
|
||||
- **文件**:`literature.py:293-294`
|
||||
- **根因**:`[str(t) for t in _tag_matches]` 将 UUID 转字符串后传给 `in_(...)`,某些驱动下可能导致类型不匹配
|
||||
- **修复**:改为 `list(_tag_matches)` 传递原生 UUID 对象
|
||||
|
||||
### 审计结果汇总
|
||||
|
||||
| 审计维度 | 结果 |
|
||||
|---------|------|
|
||||
| Normal 搜索边缘情况 | ✅ `_parse_primary` 重复 group 已修复。PubMed 降级路径 field tag 清洗已正确。ATM 展开括号剥离已正确 |
|
||||
| 前端参数发送 | ✅ SearchView.vue 完整发送全部 28 个参数,`SearchRequestBody` 类型正确 |
|
||||
| NOT 检测 | ✅ `group_negated` 新增 track,`all_not` 已替换。NOT-wrapped parens 与 sub-group 交互部分缓解(depth guard)。剩余 De Morgan 双重否定场景(LOW,理论正确性,实际罕见) |
|
||||
|
||||
---
|
||||
|
||||
截至 2026-07-29,剩余 7 项已知限制:
|
||||
|
||||
| ID | 问题 | 原因 | 影响 |
|
||||
|
||||
Reference in New Issue
Block a user