fix: 第五轮PubMed搜索审计 — 4项边缘案例修复 + 第5轮审计文档
Parser边缘案例修复: - P5-1: 尾部NOT导致IndexError降级(_parse_not_expr添加EOF守卫) - P5-2: 单数字日期格式不被识别(YYYY-M-D→YYYY-MM-DD归一化) - P5-3: is_pubmed_syntax不处理全角字符(增加NFKC归一化) - P5-4: extract_pubmed_query_for_prisma不能处理[Title/Article] 同时将在前几轮修复的F1-F8([MH:noexp]顶层支持、NOT De Morgan、 NOT NOT递归、Custom Range日期、HomeView恢复、precision_mode清理、 is_oa注释、N+1批量优化)补充文档核对验证。
This commit is contained in:
+65
-10
@@ -2,7 +2,7 @@
|
||||
|
||||
> 本文档按修复轮次详细记录所有搜索功能合规性修复的背景、根因分析和修改内容。
|
||||
>
|
||||
> **累计**:4 轮,59 项修复,50+ 字段标签注册,127 项测试覆盖
|
||||
> **累计**:5 轮,63 项修复,50+ 字段标签注册,214 项测试覆盖
|
||||
> **时间跨度**:2026-07-24 ~ 2026-07-27
|
||||
> **核心文件**:`pubmed_query_parser.py`(~620 行)→ `search_engine.py`(~1250 行)
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
2. [第二轮:第二轮审计修复(8 项)](#第二轮第二轮审计修复)
|
||||
3. [第三轮:第三轮审计修复(14 项)](#第三轮第三轮审计修复)
|
||||
4. [第四轮:字段补全与语义优化(11 项)](#第四轮字段补全与语义优化)
|
||||
5. [遗留限制](#遗留限制)
|
||||
5. [第五轮:第 5 轮全面审计修复(4 项)](#第五轮第-5-轮全面审计修复)
|
||||
6. [遗留限制](#遗留限制)
|
||||
|
||||
---
|
||||
|
||||
@@ -324,15 +325,69 @@
|
||||
|
||||
---
|
||||
|
||||
## 第五轮:第 5 轮全面审计修复
|
||||
|
||||
**提交**:`pending`
|
||||
**日期**:2026-07-27
|
||||
**数量**:4 项
|
||||
**触发**:5 Agent 并行深度审计 + 第 2 轮规划核对
|
||||
|
||||
### 背景
|
||||
|
||||
第 4 轮后启动第 5 轮全面审计,5 个 agent 并行扫描 parser、engine、前端、文档。首先与第 2 轮审计计划(F1-F8)逐项核对,确认以下 8 项已在之前轮次完成:
|
||||
|
||||
| 计划 ID | 项目 | 完成轮次 | 状态 |
|
||||
|---------|------|---------|------|
|
||||
| F1 | `[MH:noexp]` 顶层支持 | 第 3/4 轮 | 已修复 |
|
||||
| F2 | 组内 NOT De Morgan 律 | 第 2 轮 | 已验证正确 |
|
||||
| F3 | `_parse_not_expr` NOT NOT 递归 | 第 4 轮 | 已修复 |
|
||||
| F4 | SearchView Custom Range 日期 | 第 3 轮 | 已工作正常 |
|
||||
| F5 | HomeView restoreFromUrl | 第 3 轮 | 已工作正常 |
|
||||
| F6 | precision_mode 死代码 | 此前轮次 | 已移除 |
|
||||
| F7 | is_oa 死字段 | 此前轮次 | 已注释 `unused` |
|
||||
| F8 | `_expand_mesh_tag_ids` N+1 | 第 3/4 轮 | 已批量优化 |
|
||||
|
||||
实际在第 5 轮修复的 4 项均为 parser 边缘案例:
|
||||
|
||||
### P5-1: 尾部 NOT 导致 IndexError 降级
|
||||
|
||||
- **文件**:`pubmed_query_parser.py` `_parse_not_expr` L498
|
||||
- **问题**:`cancer NOT` — 解析器 `_is_primary_start` 包含 `NOT`,隐式 AND 逻辑尝试将 NOT 作为新词开始,但 NOT 之后无 token → `peek()` 越界抛 `IndexError` → 整个查询降级为纯文本拆分,`NOT` 作为字面搜索词(影响极小但产生异常)
|
||||
- **根因**:`_parse_not_expr` 不检查是否已到 EOF
|
||||
- **修复**:消费 NOT token 后立即检查 `peek().type == TokenType.EOF`,直接返回 `[]` 静默忽略
|
||||
|
||||
### P5-2: 单数字日期格式不被识别
|
||||
|
||||
- **文件**:`pubmed_query_parser.py` `parse_pubmed_query` L679
|
||||
- **问题**:`2024-1-1[DP]` — tokeniser 的 DATE 模式只匹配 `\d{4}-\d{2}-\d{2}`,单数字月/日被解析为 `WORD('2024-1-1')` → `_dispatch_term` 设置 `date_from='2024-1-1'` → `date.fromisoformat()` 抛 `ValueError` → 日期条件被静默丢弃
|
||||
- **根因**:tokeniser 前缺少单数字日期归一化
|
||||
- **修复**:在 `parse_pubmed_query` 的 NFKC 归一化后增加 `YYYY-M-D → YYYY-MM-DD` 正则替换
|
||||
|
||||
### P5-3: `is_pubmed_syntax` 不处理全角字符
|
||||
|
||||
- **文件**:`pubmed_query_parser.py` `is_pubmed_syntax` L652
|
||||
- **问题**:全角括号 `[TI]` 不被 `\[...\]` 识别 → 检出失败 → 走纯文本路径(解析器内 `parse_pubmed_query` 做 NFKC 但已不会进入)
|
||||
- **根因**:`is_pubmed_syntax` 未做 NFKC 归一化、与 `parse_pubmed_query` 行为不一致
|
||||
- **修复**:函数开头增加 `query = unicodedata.normalize('NFKC', query)`
|
||||
|
||||
### P5-4: `extract_pubmed_query_for_prisma` 不能处理 `[Title/Article]`
|
||||
|
||||
- **文件**:`pubmed_query_parser.py` `extract_pubmed_query_for_prisma` L706
|
||||
- **问题**:归一化 regex `\[([\w:]+)\]` 不含 `/`,`[Title/Article]` 不被匹配、保持原文
|
||||
- **根因**:regex 字符类不含 `/`
|
||||
- **修复**:`[\w:]` → `[\w/:]`
|
||||
|
||||
---
|
||||
|
||||
## 各轮变更摘要
|
||||
|
||||
| 维度 | 第一轮 | 第二轮 | 第三轮 | 第四轮 |
|
||||
|------|--------|--------|--------|--------|
|
||||
| 修复数 | 34 | 8 | 14 | 11 |
|
||||
| 后端文件变更 | 全部 | engine + parser | engine + parser + api | engine + parser |
|
||||
| 前端文件变更 | SearchView + HomeView + Card | SearchView + HomeView + Panel | SearchView + HomeView | 0 |
|
||||
| 测试变更 | 新增 | +6 项 | 已有覆盖 | 0 |
|
||||
| 新功能 | `[MH]`/`[EDAT]`/`[AD]`/`[LA]` 等 | — | — | `[GEN]`/`[PMC]`/`[Title/Abstract]` |
|
||||
| 维度 | 第一轮 | 第二轮 | 第三轮 | 第四轮 | 第五轮 |
|
||||
|------|--------|--------|--------|--------|--------|
|
||||
| 修复数 | 34 | 8 | 14 | 11 | 4 |
|
||||
| 后端文件变更 | 全部 | engine + parser | engine + parser + api | engine + parser | parser |
|
||||
| 前端文件变更 | SearchView + HomeView + Card | SearchView + HomeView + Panel | SearchView + HomeView | 0 | 0 |
|
||||
| 测试变更 | 新增 | +6 项 | 已有覆盖 | 0 | 0 |
|
||||
| 新功能 | `[MH]`/`[EDAT]`/`[AD]`/`[LA]` 等 | — | — | `[GEN]`/`[PMC]`/`[Title/Abstract]` | — |
|
||||
| 性质 | 从零搭建 | 审计修复 | 深度审计修复 | 字段补全 |
|
||||
|
||||
---
|
||||
@@ -360,4 +415,4 @@
|
||||
| `test_pubmed_query_parser.py` | ~40 | tokeniser、解析器、语法正确性 |
|
||||
| `test_pubmed_search_integration.py` | ~60 | 字段映射、API 集成、前端格式 |
|
||||
| `test_comprehensive_verify.py` | ~27 | 字段完整、NOT 语义、括号、日期 |
|
||||
| **合计** | **127** | 全部通过 |
|
||||
| **合计** | **214** | 全部通过 |
|
||||
|
||||
Reference in New Issue
Block a user