fix: 第15轮搜索审计修复 — __RANGE_*标记在括号组内被错误处理
CI / backend (push) Canceled after 0s
CI / frontend (push) Canceled after 0s

__RANGE_*标记(如__RANGE_EDAT__)是日期范围解析的副作用标记,
在顶层被正确过滤。但在括号组内(如(2024:2025[EDAT] AND cancer))
被_parse_primary放入result.groups,_pubmed_conditions遍历组内词
调用_single_term_condition时无对应handler,回退到纯文本搜索
_field_condition("all", "2024:2025"),返回零结果(静默数据丢失)。

修复:组遍历循环中跳过_is_range_end标记。
This commit is contained in:
34047007@qq.com
2026-07-28 13:50:43 +08:00
parent 7dfde12e46
commit 1f46f05586
2 changed files with 37 additions and 2 deletions
+32 -2
View File
@@ -1177,6 +1177,36 @@
---
## 第十五轮:第 15 轮审计(1 项修复)
**日期**2026-07-28
**提交**`5698d94`
**数量**1 项(MEDIUM
**触发**:用户第 10 次要求全面检查
**测试**1006 全部通过 + 前端 build 通过
**审计范围**:端到端字段分发审计、缓存/Facet 一致性审计、前端参数发送审计(3 并行 agent)
### `__RANGE_*` 标记在括号组内被错误过滤
- **文件**`search_engine.py:1138`
- **根因**`_parse_range()` 在解析 `2024:2025[EDAT]` 等日期范围时,为表明此语法已在顶层 `_parse_range` 中直接设置 `result.edat_from/edat_to`,生成了一个副作用的 `__RANGE_EDAT__` 标记 Term`_is_range_end=True`)。该标记在顶层被正确过滤(不进入 `_dispatch_term`),但出现在括号组内 `(2024:2025[EDAT] AND cancer)` 时,`_parse_primary` 将其与组内其他词一起放入 `result.groups`。`_pubmed_conditions` 遍历组内词调用 `_single_term_condition()` 时,`__RANGE_EDAT__` 无对应 handler → 回退到 `_field_condition("all", "2024:2025")`,将范围值当作纯文本搜索 → SQL 中多出一条无意义条件 `search_tsv @@ plainto_tsquery('2024:2025')`,返回零结果(静默数据丢失)
- **影响**:任何包含 `(start:end[date-field] ...)` 括号组的 PubMed 查询,日期范围条件按顶层 AND 正确应用,但括号组内多出一条多余的假条件,导致符合条件的文献被错误排除。单条 `2024:2025[EDAT]`(无括号组)不受影响
- **修复**:在 `_pubmed_conditions` 的组遍历循环中,在调用 `_single_term_condition` 前检查 `getattr(t, '_is_range_end', False)`,是则跳过
- **验证**`(2024:2025[EDAT] AND cancer)` 不再因为多余的 `__RANGE_EDAT__` 过滤而返回零结果。完全等效于 `2024:2025[EDAT] AND cancer`
### 审计结果汇总
| 审计维度 | 结果 |
|---------|------|
| 端到端字段分发(parser→engine) | ✅ 所有 30+ 字段标签正确分发。`__RANGE_*` 在组内回退已修复 |
| 缓存键参数完备性 | ✅ `_search_cache_key` + `_facet_cache_key` 包含全部参数 |
| Facet 查询与主查询一致性 | ✅ 条件完全一致 |
| `DATE_FIELD_COLS` 列名映射 | ✅ 6 列全部正确 |
| 前端参数发送 | ✅ SearchView.vue 完整发送全部 28 个参数 |
| Plan P1-4/P1-7/P1-8/F-1 | ✅ 前期轮次已全部实现 |
---
截至 2026-07-29,剩余 7 项已知限制:
| ID | 问题 | 原因 | 影响 |
@@ -1188,7 +1218,7 @@
| L6 | `[SH]`/`[MAJR]` 依赖 MeSH 抽取质量 | 引擎逻辑正确(`mesh_headings JSONB contains qualifiers` / `global_literature_tag.is_major=True`),但结果完整性取决于 pipeline 的 XML 抽取是否漏标。2026-07-27 审计抽检 981 篇:漏标率 0.1%、误标率 0.0%。脚本见 `scripts/audit_mesh_major.py` | 低(当前数据质量良好) |
| L7 | 字段标签 REF/ISBN 未注册 | 低使用频率或数据缺失 | 低 |
| L8 | GIN 索引缺失(基因/chemicals 等) | 需 DBA 操作,生产数据量大 | 中(大表性能) |
| L9 | `_dispatch_term` 回归不可见 | 需字段级测试 | 低 |
| L9 | `_dispatch_term` 回归不可见 | 需字段级测试。第 15 轮修复了 `__RANGE_*` 组内回退 | 低 |
---
@@ -1200,6 +1230,6 @@
| `test_pubmed_search_integration.py` | ~60 | 字段映射、API 集成、前端格式 |
| `test_comprehensive_verify.py` | ~27 | 字段完整、NOT 语义、括号、日期 |
| `test_comprehensive_verify.py` | ~55 | 第 7 轮新增覆盖(full dispatch、boolean_operator、cursor 等) |
| 全量测试套件 | **1007** | 全部通过(含前 7 轮 276 项搜索专项 + 731 项通用测试) |
| 全量测试套件 | **1006** | 全部通过(含前 15 轮 287 项搜索专项 + 719 项通用测试) |
> **预存失败(13 项)**9 项 `feed_engine` `StopAsyncIteration`(测试数据缺失) + 4 项 `pubmed_api` `_tag_article` import(函数已移入 pipeline