feat: 第四轮PubMed搜索字段补全 — 11项修复
CI / backend (push) Canceled after 0s
CI / frontend (push) Canceled after 0s

- [Title/Abstract]/[OAB]/[WORD]/[FI]/[SO]/[PL] 注册
- [GEN] 基因符号搜索 → gene_symbols JSONB
- [PMC] PMCID 搜索 → pmc_id 列
- [OT] 语义修复 → keywords JSONB(不再映射到 all)
- phraseto_tsquery 精确短语(GIN 索引替代 ILIKE)
- has_pubmed_terms 门控补全新字段
- 127 项搜索测试全部通过,前端构建无报错
This commit is contained in:
34047007@qq.com
2026-07-27 11:19:10 +08:00
parent 6a8eb70dde
commit 807972d41b
4 changed files with 117 additions and 20 deletions
+36 -12
View File
@@ -1,10 +1,11 @@
# 搜索功能差距分析:与 PubMed 对比
> **原始审计日期**2026-07-249 Agent 审计)
> **已修复至**2026-07-27轮修复,共 48 项 fix
> **已修复至**2026-07-27轮修复,共 56+ 项 fix
> - 第一轮 Phase 1-734 项修复(parser + engine + frontend
> - 第二轮审计:8 项修复(MH:noexp, De Morgan, 重复 NOT, Custom Range 等)
> - 第三轮审计:14 项修复(SB/STAT/UID 门控, 日期精度, [ALL] 注册, 参数验证等)
> - 第四轮审计:8 项字段注册 + 3 项语义修复 + phraseto_tsquery
> **测试状态**:127 项搜索测试全部通过,前端构建无报错
>
> 本文档作为持续差距追踪使用,**已完成项**已标记 ✅,当前阻塞项用 🚧 标注。
@@ -111,7 +112,7 @@ publication_status: ppublish=544, epublish=530, aheadofprint=478
| `[SB]` 子集 | medline/pubmed/代码 | ✅ | 第三轮回定:medline→statuspubmed→no-op |
| `[STAT]` 状态 | citation status | ✅ | — |
| `[UID]` PMID | 数字+DOI | ✅ | — |
| `[OT]` 其他关键词 | 关键词文本 | ⚠️ 映射到 "all" | **语义过宽**,需 keyword 独立字段 |
| `[OT]` 其他关键词 | 关键词文本 | ✅ keywords JSONB contains | P4 修复:不再映射到 all |
| `[GR]` 基金号 | 基金信息 | ✅ JSONB contains | — |
| `[NM]` (substance) | 化学物质名 | ✅ JSONB contains | — |
| `[RN]` 注册号 | Registry Number | ✅ | — |
@@ -129,12 +130,17 @@ publication_status: ppublish=544, epublish=530, aheadofprint=478
| `[VI]`/`[IP]`/`[PG]` | 卷/期/页码 | ✅ | — |
| `[LID]` 文献 ID | e-location ID | ✅ | — |
| `[PMID]`/`[DOI]` | 精确匹配 | ✅ | — |
| `[PL]` 出版地 | 国家/城市 | ❌ | 未注册字段标签 |
| `[SO]` 来源 | 期刊+卷+页码 | ❌ | 未注册字段标签 |
| `[PMC]` PMCID | 精确匹配 | ❌ | 数据覆盖率问题 |
| `[GEN]` 基因符号 | 基因 | ❌ | 数据 0% |
| `[PL]` 出版地 | 国家/城市 | ✅ 映射到 journal | P4 注册 |
| `[SO]` 来源 | 期刊+卷+页码 | ✅ 映射到 journal | P4 注册 |
| `[PMC]` PMCID | 精确匹配 | ✅ pmc_id 精确搜索 | P4 注册(数据覆盖率问题 |
| `[GEN]` 基因符号 | 基因 | ✅ gene_symbols JSONB | P4 注册 |
| `[FI]` 基金标识符 | Funder ID | ✅ 同 GR 路径 | P4 注册 |
| `[OAB]` 其他摘要 | Other Abstract | ✅ 映射到 all | P4 注册 |
| `[WORD]` 文本词 | Word in text | ✅ 映射到 all | P4 注册 |
| `[Title/Abstract]` 长标签 | 标题+摘要 | ✅ 映射到 all | P4 注册 |
| `[REF]` 引用关系 | 引用文献 | ❌ | 功能缺失 |
| `[ALL]` `[OAB]` `[WORD]` 等 | 其他标签 | ❌ | 静默降级到 plain_text |
| `[ISBN]` 图书 ISBN | 图书 | ❌ | 仅图书相关 |
| 其余未注册标签 | 低频 | ❌ | 静默降级到 plain_text |
| 通配符 `*` | 单/多字符 | ❌ | plainto_tsquery 不支持 |
| 精确短语 `"..."` | phraseto_tsquery | ⚠️ ILIKE 回退 | GIN 索引未利用 |
| AND/OR/NOT 布尔 | 从左到右优先级 | ⚠️ | AND>OR 优先级(已知 L1 |
@@ -183,6 +189,22 @@ publication_status: ppublish=544, epublish=530, aheadofprint=478
| P3-5 | GET search 无查询长度限制 | `literature.py` | 100 词上限 |
| P3-6 | 中文正则不一致 | `query_expansion.py` | `[一-鿿㐀-䶿豈-﫿]` 同步 |
### ✅ 已修复 — 第四阶段(11 项)
| # | 修复项 | 文件 | 说明 |
|---|--------|------|------|
| P4-1 | [Title/Abstract] 长标签注册 | `pubmed_query_parser.py` | 新增 `_ALL_FIELD_TAGS` + `_FIELD_TAG_MAP` |
| P4-2 | [OAB] 注册 | `pubmed_query_parser.py` | Other Abstract 映射到 all |
| P4-3 | [WORD] 注册 | `pubmed_query_parser.py` | Word in text 映射到 all |
| P4-4 | [FI] 注册 | `pubmed_query_parser.py` | Funder Identifier 同 GR 路径 |
| P4-5 | [SO] / [PL] 注册 | `pubmed_query_parser.py` | Source / Place 映射到 journal |
| P4-6 | [GEN] 基因符号搜索 | `pubmed_query_parser.py` + `search_engine.py` | 接通 gene_symbols JSONB,加 dispatch + SQL |
| P4-7 | [PMC] PMCID 搜索 | `pubmed_query_parser.py` + `search_engine.py` | 接通 pmc_id 列,加 dispatch + SQL |
| P4-8 | [OT] 语义修复 | `pubmed_query_parser.py` + `search_engine.py` | OT→keywords JSONB,不再映射到 all |
| P4-9 | has_pubmed_terms 门控补全 | `search_engine.py` | 两处 gate 加 ot_terms/gene_terms/pmc_terms |
| P4-10 | phraseto_tsquery 精确短语 | `search_engine.py` | 全字段精确短语使用 GIN 索引而非 ILIKE |
| P4-11 | 解析器注册同步 | `pubmed_query_parser.py` | _SPECIAL_FIELDS + _dispatch_term 同步 |
---
## 5. 当前遗留限制(不改或需架构变更)
@@ -193,8 +215,8 @@ publication_status: ppublish=544, epublish=530, aheadofprint=478
| L2 | Affiliation JSONB cast 假阳性 | 需独立 affiliation 列 + Alembic 迁移 + 重新填充 |
| L3 | retracted "yes"="only" | 命名语义,SQL 条件相同 |
| L4 | OR-mode NOT 检测不可靠 | `UnaryExpression + _sa_ops.inv` 不可靠用于复合 NOT |
| L5 | `[OT]` 映射到 "all" 语义过宽 | 需 keyword 独立 JSONB 列 + 抽取补充 |
| L6 | 15 个字段标签未注册(PL/SO/PMC/GEN/REF 等) | 低使用频率或数据缺失 |
| L5 | ~~`[OT]` 映射到 "all" 语义过宽~~ | ✅ P4 已修复:映射到 keywords JSONB |
| L6 | 字段标签未注册(REF/ISBN 等) | 低使用频率或数据缺失,不影响核心功能 |
| L7 | GIN 索引缺失(多个 JSONB 列) | 需 DBA 操作,生产数据量大 |
| L8 | `_dispatch_term` 回归不可见 | 需字段级测试(现有测试不验证分发目的地) |
@@ -202,16 +224,18 @@ publication_status: ppublish=544, epublish=530, aheadofprint=478
## 6. 结论
**搜索功能已基本达到与 PubMed 对等的核心能力。** 经过轮共 48 项修复:
**搜索功能已基本达到与 PubMed 对等的核心能力。** 经过轮共 59 项修复:
- 42+ 字段标签完整注册并接通搜索路径(仅 7 个低频标签未注册)
- 50+ 字段标签完整注册并接通搜索路径(仅 REF/ISBN 等低频标签未注册)
- 所有日期字段(DP/EDAT/CRDT/MHDA/LR/DCOM/DEP)范围+独立语法均支持
- MeSH 树展开 + 入口词匹配 + ATM 自动术语映射正常工作
- 布尔运算 NOT/AND/OR + 括号分组 + 重复 NOT 正确处理
- [GEN] 基因符号/ [PMC] PMCID / [OT] 关键词 独立语义搜索
- 精确短语 phraseto_tsquery 利用 GIN 索引
- 前端搜索参数 URL 全量持久化,日期精度保留
- sort/field/boolean 参数经过验证拒绝非法值
- 127 项搜索测试覆盖全部场景
**剩余 8 项限制**(L1-L8)属于架构性改进或低频场景,不影响搜索功能的日常使用。核心阻塞项已全部解除。
**剩余 7 项限制**L1-L4, L6-L8)属于架构性改进或低频场景,不影响搜索功能的日常使用。核心阻塞项已全部解除。
详细实施状态见 [12-搜索功能实施计划.md](12-搜索功能实施计划.md)。