2026-07-27 07:59:18 +08:00
|
|
|
|
# 搜索功能差距分析:与 PubMed 对比
|
|
|
|
|
|
|
|
|
|
|
|
> 审计日期:2026-07-24
|
|
|
|
|
|
> 数据基准:本地 PG 数据库 1,662 篇文献(seed_data: 110, pubmed_api: 1,552)
|
|
|
|
|
|
> 分析方法:9 Agent 审计 + 真实数据库字段覆盖率查询
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 1. 现状概览
|
|
|
|
|
|
|
|
|
|
|
|
当前搜索系统架构:
|
|
|
|
|
|
|
|
|
|
|
|
- **查询解析**:`backend/app/services/pubmed_query_parser.py` — 递归下降解析器,支持 11 个字段标签,AND/OR/NOT 布尔
|
|
|
|
|
|
- **搜索引擎**:`backend/app/services/search_engine.py` — PostgreSQL tsvector GIN 索引 + ILIKE 回退
|
|
|
|
|
|
- **前端入口**:`SearchView.vue`(主搜索页)+ `AdvancedSearchPanel.vue`(高级筛选面板)
|
|
|
|
|
|
- **API 端点**:`POST /features/search/advanced`(主要)+ `GET /literature/search`(死代码)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 2. 数据充分性评估
|
|
|
|
|
|
|
|
|
|
|
|
### 2.1 充分字段(可直接支撑搜索)
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 覆盖率 | 用途 |
|
|
|
|
|
|
|------|--------|------|
|
|
|
|
|
|
| `pmid` | 1,662/1,662 (100%) | `[PMID]` 精确搜索 |
|
|
|
|
|
|
| `title` | 1,652/1,662 (99.4%) | `[TI]` 全文搜索 |
|
|
|
|
|
|
| `abstract` | 1,550/1,662 (93.3%) | `[AB]` 全文搜索 |
|
|
|
|
|
|
| `doi` | 1,548/1,662 (93.1%) | `[DOI]` 精确搜索 |
|
|
|
|
|
|
| `authors` (JSON) | 1,659/1,662 (99.8%) | `[AU]` `[AD]` 搜索 |
|
|
|
|
|
|
| `pub_types` (JSON) | 1,557/1,662 (93.7%) | `[PT]` 筛选 |
|
|
|
|
|
|
| `journal` | 1,662/1,662 (100%) | `[TA]` 全称搜索 |
|
|
|
|
|
|
| `publication_status` | 1,552/1,662 (93.4%) | 状态筛选 |
|
|
|
|
|
|
| `pub_year` | 1,662/1,662 (100%) | `[DP]` 年份搜索 |
|
|
|
|
|
|
| `pub_date` | 1,148/1,662 (69.1%) | `[DP]` 日期搜索 |
|
|
|
|
|
|
| `language` | 1,644/1,662 (98.9%) | `[LA]` 搜索 |
|
|
|
|
|
|
| `search_tsv` | 1,662/1,662 (100%) | tsvector GIN 全文搜索 |
|
|
|
|
|
|
| `mesh_headings` (JSON) | 845/1,662 (50.8%) | MeSH 展示(搜索由 literature_tags 完成) |
|
|
|
|
|
|
| `literature_tags` | 997 条关联 | `[MH]`/`[MAJR]` 搜索 |
|
|
|
|
|
|
| `grants` (JSON) | 323/1,662 (19.4%) | `[GR]` 搜索 |
|
|
|
|
|
|
| `chemical_list` (JSON) | 508/1,662 (30.6%) | `[NM]` 搜索 |
|
|
|
|
|
|
| `study_design` (JSON) | 1,552/1,662 (93.4%) | 临床研究设计筛选 |
|
|
|
|
|
|
|
|
|
|
|
|
### 2.2 严重不足字段
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 覆盖率 | 影响 | 优先级 |
|
|
|
|
|
|
|------|--------|------|--------|
|
|
|
|
|
|
| `journal_iso` | **0/1,662 (0%)** | `[TA]` 缩写期刊搜索完全不可用 | **P0** |
|
|
|
|
|
|
| `tree_numbers` | **0 行数据** | `_expand_mesh_tag_ids` INNER JOIN → 所有 `[MH]`/`[MAJR]` 查询返回 0 结果 | **P0** |
|
|
|
|
|
|
| `keywords` (JSON) | **0/1,662 (0%)** | `[OT]` 其他关键词搜索不可用 | **P1** |
|
|
|
|
|
|
| `pmc_id` | **9/1,662 (0.5%)** | XPath bug,`[PMC]` 搜索和 PMC OA 全文抓取不可用 | **P1** |
|
|
|
|
|
|
| `gene_symbols` (JSON) | **0%** | 基因符号搜索不可用 | P2 |
|
|
|
|
|
|
| `is_negative_result` | 仅 pubmed_api 来源有 | 构造函数遗漏 seed_data | **P1** |
|
|
|
|
|
|
| `retraction_details` | **0%** | 全库无撤稿记录 | P3 |
|
|
|
|
|
|
| `full_text_sections` | **0.4%** | PMC OA 全文解析进度 | P3 |
|
|
|
|
|
|
|
|
|
|
|
|
### 2.3 核心数据指标
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
总计: 1,662 篇
|
|
|
|
|
|
年份分布: 2025=58, 2026=1,604 (96.5% ∈ 2026)
|
|
|
|
|
|
标签: 99 个 (全部 manual, 28 个未关联任何文献)
|
|
|
|
|
|
文献-标签: 997 条 (946 major, 51 non-major)
|
|
|
|
|
|
每篇标签数: P25=1, P50=1, P75=2, P90=5, P99=6
|
|
|
|
|
|
被引次数: median=0, avg=0.6, max=491
|
|
|
|
|
|
撤稿: 0 篇
|
|
|
|
|
|
语言分布: eng=1,496, en=110, chi=35, jpn=7, rus=4
|
|
|
|
|
|
citation_status: MEDLINE=502, Publisher=254, In-Process=64, PubMed-not-MEDLINE=59
|
|
|
|
|
|
publication_status: ppublish=544, epublish=530, aheadofprint=478
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 3. 与 PubMed 搜索功能差距矩阵
|
|
|
|
|
|
|
|
|
|
|
|
| 搜索功能 | PubMed | 当前系统 | 差距 |
|
|
|
|
|
|
|---------|--------|---------|------|
|
|
|
|
|
|
| 纯文本搜索 (title/abstract) | tsvector + 权重 | ✅ tsvector + GIN | 无 setweight |
|
|
|
|
|
|
| `[TI]` 标题字段 | 精确 + 词干 | ✅ | — |
|
|
|
|
|
|
| `[AB]` 摘要字段 | 精确 + 词干 | ✅ | — |
|
|
|
|
|
|
| `[AU]` 作者字段 | 精确 + 自动截词 | ✅ (ILIKE) | exact 参数被忽略 |
|
|
|
|
|
|
| `[TA]` 期刊字段 | 全称 + 缩写 | ❌ journal_iso 0% | **未实现** |
|
|
|
|
|
|
| `[MH]` MeSH 字段 | tree_number 展开 + 子树 | ❌ INNER JOIN 0 结果 | **Bug** |
|
|
|
|
|
|
| `[MAJR]` 主要 MeSH | 同上 + major | ❌ 同上 | **Bug** |
|
|
|
|
|
|
| `[MH:NoExp]` 不展开 | 精确 MeSH | ❌ 解析器不支持 | **未实现** |
|
|
|
|
|
|
| `[PT]` 文献类型 | 精确匹配 | ✅ JSONB contains | — |
|
|
|
|
|
|
| `[DP]` 出版日期 | 范围 + 格式灵活 | ✅ 年份/日期 | 单值年份 bug |
|
|
|
|
|
|
| `[LA]` 语言 | 2 字母代码 | ❌ 解析器无映射 | **未实现** |
|
|
|
|
|
|
| `[AD]` 机构 | 地址文本 | ❌ 解析器无映射 | **未实现** |
|
|
|
|
|
|
| `[EDAT]` 入库日期 | 精确日期 | ❌ 字段不存在 | **未实现** |
|
|
|
|
|
|
| `[OT]` 其他关键词 | 关键词文本 | ❌ keywords 0% | **未实现** |
|
|
|
|
|
|
| `[GR]` 基金号 | 基金信息 | ❌ 解析器无映射 | **未实现** |
|
|
|
|
|
|
| `[NM]` 化学物质 | 化学物质名 | ❌ 解析器无映射 | **未实现** |
|
|
|
|
|
|
| `[TW]` 文本词 | 全字段文本 | ❌ 解析器无映射 | **未实现** |
|
|
|
|
|
|
| `[ALL]` 全字段 | 等价于无标签 | ❌ 被静默丢弃 | **Bug** |
|
|
|
|
|
|
| `[PMC]` PMCID | 精确匹配 | ❌ XPath bug 数据不足 | **Bug** |
|
|
|
|
|
|
| 通配符 `*` | 单/多字符 | ❌ plainto_tsquery 不支持 | **未实现** |
|
|
|
|
|
|
| 精确短语 `"..."` | phraseto_tsquery | ❌ ILIKE 回退 | **未实现** |
|
|
|
|
|
|
| AND/OR/NOT 布尔 | 从左到右优先级 | ⚠️ AND>OR 优先级 | Bug |
|
|
|
|
|
|
| `:NoExp` 后缀 | MeSH 不展开 | ❌ 解析器不支持 | **未实现** |
|
|
|
|
|
|
| `[Title/Abstract]` 长标签 | 标题+摘要 | ❌ 仅 TIAB | **未实现** |
|
|
|
|
|
|
| **ATM** 自动术语映射 | MeSH + Journal + Author 翻译 | ❌ **完全缺失** | **P0** |
|
|
|
|
|
|
| **Entry Terms** 入口词 | ~200k 同义词 | ❌ **完全缺失** | **P1** |
|
|
|
|
|
|
| **搜索历史 #1 AND #2** | 会话级历史链 | ❌ **完全缺失** | P2 |
|
|
|
|
|
|
| **搜索建议/自动补全** | MeSH + Author + Journal | ❌ **完全缺失** | P2 |
|
|
|
|
|
|
| **搜索结果排序** | 相关度 + 日期 + 被引 | ⚠️ best_match 权重公式错误 | Bug |
|
|
|
|
|
|
| **ts_rank 权重** | title(A) > abstract(B) | ❌ 全部相同 | **未实现** |
|
|
|
|
|
|
| **Faceted 筛选** | 文献类型 + 日期 + 语言 | ❌ **完全缺失** | P2 |
|
|
|
|
|
|
| **Spell correction** | "Did you mean" | ❌ **完全缺失** | P3 |
|
|
|
|
|
|
| **搜索高亮** | 匹配词高亮 | ❌ **完全缺失** | P3 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 4. 关键 Bug 清单(按严重性排列)
|
|
|
|
|
|
|
|
|
|
|
|
### 🚨 CRITICAL(7 个)
|
|
|
|
|
|
|
|
|
|
|
|
| # | Bug | 位置 | 描述 |
|
|
|
|
|
|
|---|-----|------|------|
|
|
|
|
|
|
| 1 | `recent_subq` 破坏历史搜索 | `search_engine.py:314-319` | `sort=date` 时预取最近 2000 篇 ID(无条件),早期文献搜索 0 结果 |
|
|
|
|
|
|
| 2 | OR 布尔被 AND 替代 | `search_engine.py:387-414` | 所有 field_map 条件 `and_()` 合并,`result.boolean_operator` 未被消费 |
|
|
|
|
|
|
| 3 | 多 [MH] 词用 OR 而非 AND | `search_engine.py:516-519` | 所有 mesh term 同一 `or_()` 子查询 |
|
|
|
|
|
|
| 4 | Date Sort Optimization 无条件 | `search_engine.py:314` | 无 80% 匹配率门槛,固定 2000 篇限制 |
|
|
|
|
|
|
| 5 | PMC/trial_reg XPath 上下文错误 | `pubmed_api.py:440,447` | 在 `MedlineCitation/Article` 下搜 `ArticleIdList`(实际在 `PubmedData` 下) |
|
|
|
|
|
|
| 6 | 5 字段构造函数遗漏 | `pubmed_api.py:914-944` | `pubmed_revised`/`citation_status`/`date_completed`/`article_date`/`suppl_mesh_list` |
|
|
|
|
|
|
| 7 | `_expand_mesh_tag_ids` INNER JOIN | `search_engine.py:518` | `global_tag_tree_numbers` 0 行 → 全部 [MH] 查询 0 结果 |
|
|
|
|
|
|
|
|
|
|
|
|
### 🟡 HIGH(12 个)
|
|
|
|
|
|
|
|
|
|
|
|
| # | Bug | 位置 | 描述 |
|
|
|
|
|
|
|---|-----|------|------|
|
|
|
|
|
|
| 8 | `ArticleTitle.text` | `pubmed_api.py:409` | 跳过嵌套 `<i>` 等标签 |
|
|
|
|
|
|
| 9 | `[TA]` 不搜 journal_iso | `search_engine.py:476` | 缩写期刊名零结果 |
|
|
|
|
|
|
| 10 | `_field_condition("all")` exact 不搜 abstract | `search_engine.py:482-486` | 精确短语只在 title 内搜 |
|
|
|
|
|
|
| 11 | `_field_condition` exact 被 author/journal 忽略 | `search_engine.py:473-478` | exact 参数传递中断 |
|
|
|
|
|
|
| 12 | 中文 → English tsquery 零结果 | `search_engine.py:123-149` | 中文不经过词干分析 |
|
|
|
|
|
|
| 13 | `best_match` 权重被淹没 | `search_engine.py:556-558` | ts_rank*0.3 vs recency+5, ln(cited)*2 |
|
|
|
|
|
|
| 14 | tsvector 无 setweight | 迁移文件 | title/abstract/author/affiliation 权重相等 |
|
|
|
|
|
|
| 15 | 多 affiliation 仅取第一个 | `pubmed_api.py:427` | `find` 而非 `findall` |
|
|
|
|
|
|
| 16 | CommentsCorrections 仅撤稿 | `pubmed_api.py:484-497` | 仅 `RetractedBy`/`RetractionOf`,缺 ~18 个 RefType |
|
|
|
|
|
|
| 17 | Entry Terms 无法导入 | `scripts/import_mesh_tags.py` | mtrees.bin 无 entry terms,需 asc 解析器 |
|
|
|
|
|
|
| 18 | PMC_ID 格式不一致 | `pubmed_api.py:264,442` | Europe PMC 带 "PMC" 前缀,XML 路径纯数字 |
|
|
|
|
|
|
| 19 | Europe PMC 7 字段 None | `pubmed_api.py:170-299` | `pubmed_revised`/`citation_status`/`date_completed`/`trial_reg`/`retraction_details`/`grants`/`article_date` |
|
|
|
|
|
|
|
|
|
|
|
|
### 🟠 MEDIUM(9 个)
|
|
|
|
|
|
|
|
|
|
|
|
| # | Bug | 位置 | 描述 |
|
|
|
|
|
|
|---|-----|------|------|
|
|
|
|
|
|
| 20 | 搜索端点无 try/except | `features.py:68` | 异常 → 500 |
|
|
|
|
|
|
| 21 | DISMISS_THRESHOLD 从未检查 | `literature.py:23` | 已读/忽略过滤失效 |
|
|
|
|
|
|
| 22 | SynonymExpander 零引用 | `backend/app/services/synonym_expander.py` | 312 行死代码 |
|
|
|
|
|
|
| 23 | `import re` 在函数内 | `search_engine.py:113` | 每次调用重新 import |
|
|
|
|
|
|
| 24 | 前端 field:all 硬编码 | `SearchView.vue:83` | AdvancedSearchPanel 形同虚设 |
|
|
|
|
|
|
| 25 | `[ALL]` 标签静默丢弃 | `pubmed_query_parser.py:40,69` | 不在 FIELD 集合 |
|
|
|
|
|
|
| 26 | `[Title/Abstract]` `[MeSH]` 不被识别 | `pubmed_query_parser.py:40,69` | 只识别短标签 |
|
|
|
|
|
|
| 27 | exact 被 MeSH/Author 丢弃 | `search_engine.py:474,516` | ILIKE 模糊匹配 |
|
|
|
|
|
|
| 28 | 查询构建代码重复 | `search_engine.py:225-250,273-288` | 两段完全相同 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 5. 结论
|
|
|
|
|
|
|
2026-07-27 08:35:12 +08:00
|
|
|
|
**硬性要求:搜索功能必须与 PubMed 完全一致。**
|
2026-07-27 07:59:18 +08:00
|
|
|
|
|
2026-07-27 08:35:12 +08:00
|
|
|
|
这意味着:
|
|
|
|
|
|
1. **所有 PubMed 字段标签**必须有对应的搜索路径(数据已存储的立即接通,未存储的补充抽取)
|
|
|
|
|
|
2. **所有搜索行为**(MeSH 展开、ATM 映射、布尔运算、日期范围、精确短语等)必须与 PubMed 一致
|
|
|
|
|
|
3. **不允许任何字段标签退化到纯文本搜索**——`[IP]`、`[VI]`、`[PG]`、`[LA]`、`[GR]`、`[NM]`、`[SH]`、`[EDAT]`、`[CRDT]`、`[MHDA]`、`[LR]`、`[DCOM]`、`[LID]`、`[AUID]`、`[COIS]`、`[SI]` 等,凡数据已存储的必须接通,缺失数据的补充抽取
|
2026-07-27 07:59:18 +08:00
|
|
|
|
|
2026-07-27 08:35:12 +08:00
|
|
|
|
**当前阻塞或缺失项**:
|
|
|
|
|
|
|
|
|
|
|
|
| 问题 | 严重性 | 说明 |
|
|
|
|
|
|
|------|--------|------|
|
|
|
|
|
|
| MeSH 搜索 — tree_numbers 空表 + INNER JOIN | **阻塞** | 所有 `[MH]`/`[MAJR]` 查询返回 0 结果 |
|
|
|
|
|
|
| 期刊缩写搜索 — `journal_iso` 覆盖率 0% | **阻塞** | `[TA]` 缩写搜索不可用 |
|
|
|
|
|
|
| ATM 自动术语映射 — Entry Terms 缺失 | **缺失** | 普通用户输入"lung cancer"不会触发 MeSH 展开 |
|
|
|
|
|
|
| 精确短语 — `phraseto_tsquery` 未使用 | **缺失** | `"lung cancer"` 精确搜索低效 |
|
|
|
|
|
|
| 字段标签未接通(15+ 个) | **缺失** | 数据已存储但解析器未路由到搜索 |
|
|
|
|
|
|
| 作者 ORCID 数据 — `[AUID]` | **缺失** | PubMed XML 中有 `<Identifier>` 但未抽取 |
|
|
|
|
|
|
| 搜索排名 — `best_match` 权重公式错误 | **Bug** | ts_rank 几乎不影响排序 |
|
2026-07-27 07:59:18 +08:00
|
|
|
|
|
|
|
|
|
|
详细实施步骤见 [12-搜索功能实施计划.md](12-搜索功能实施计划.md)。
|
|
|
|
|
|
数据统计详情见 [13-文献数据质量报告.md](13-文献数据质量报告.md)。
|