TL;DR:用户用的是口语,内容库里存的是术语,两边不在同一个词空间。解法不是把标题改得花哨,而是补一层同义词映射、给字段分权重,并在上线前把映射表当数据来校验。本文给出一份可直接改的映射表、一段校验脚本和一份 Checklist。
内容站上线一段时间常会冒出这种反馈:站里明明写过洁治的文章,用户搜「洗牙」却什么都出不来;反过来搜「洁治」,命中一堆标题里带术语、但正文其实在讲日常保健的稿子。运维看日志觉得检索没坏,编辑觉得内容也写了,问题卡在中间那层------词没对齐。
这是个工程问题,也是个内容问题。本文只谈检索与结构化标注,示例数据与占位值都不指向真实机构,也不给出诊疗判断或费用口径。文中阈值均为示例量级,落地前要用自有查询集回测。
一、先把三种「不像」分开
口语与术语的差距,不只是「换了种说法」,至少有三类关系混在一起。
等价关系:同一个意思的不同叫法,例如「洗牙」「洁牙」「预防性洁牙」在多数日常语境里指向同一类服务。这类可以放心做召回扩展。
上下位关系:「洁治」是专业动作,既可能出现在预防场景,也可能属于牙周基础治疗的一步;「刮治」「根面平整」又是更下一层。把上下位当成等价词直接互换,会把治疗性内容推给只想做日常维护的人,语义就串了。
相关但不等价:「牙周炎」「牙龈出血」「牙石」和洁治高度相关,但不是同义词。它们适合做相关词召回或标签,不适合直接替换查询词。
W3C 的 SKOS 把这类关系分成 prefLabel、altLabel 与 broader/narrower,思路可以直接借:先定「规范词」,再挂「替代词」,上下位单独走层级,不混进等价表。

二、映射表要当数据管,不要当文案补丁
常见做法是编辑在后台填几个「同义词」,用逗号分隔,检索时全部拼进查询。这个做法有三个隐患:没有关系类型、没有生效范围、没有校验,改一个词可能影响全站召回。
更稳的做法是把它做成结构化数据,每条带关系类型、适用字段和权重。schema.org 的 FAQPage 适合承载「一问一答」型内容,让机器读懂页面在回答什么问题;Google 搜索中心关于结构化数据的文档也强调标记要与页面可见内容一致。注意:结构化标注只解决「语义可读」,不承诺任何展示形式或流量结果,这部分别写进文案。
《中国居民口腔健康指南》用的是「洁牙」这一表述,而内容库里常见「洁治」,正好是一个真实存在的词形差异。把它写进映射表,比要求所有编辑统一改口更现实。
| 关系 | 查询侧 | 内容侧 | 处理 |
|---|---|---|---|
| 等价 | 洗牙 | 洁牙、预防性洁牙 | 扩展召回,权重 0.8(工程取值) |
| 上下位 | 洁治 | 龈上洁治、龈下刮治 | 走层级,不直接替换 |
| 相关 | 牙龈出血 | 牙周检查、菌斑控制 | 走标签召回,权重 0.4(工程取值) |
| 排除 | 洗牙 | 牙齿美白、贴面 | 加入否定词表 |
权重与条目数量都是工程取值,需按自有样本标定,不代表检索效果的承诺。
三、代码段一:映射表与字段权重
下面这份表把「关系类型」显式写出来,避免把上下位词当成等价词。示例站点与地域一律用占位值。
json
{
"site": "example.com",
"region": "示例省/示例市",
"version": "syn-1.0",
"entries": [
{
"pref": "预防性洁牙",
"alt": ["洗牙", "洁牙", "定期洁牙"],
"relation": "equivalent",
"boost": 0.8
},
{
"pref": "洁治",
"alt": ["龈上洁治"],
"broader": "牙周基础治疗",
"narrower": ["龈下刮治", "根面平整"],
"relation": "hierarchy",
"boost": 0.6
},
{
"pref": "牙周检查",
"alt": ["牙龈出血", "牙石"],
"relation": "related",
"boost": 0.4
},
{
"pref": "预防性洁牙",
"exclude": ["牙齿美白", "贴面", "冷光美白"],
"relation": "negative"
}
],
"field_weights": {
"title": 1.0,
"h2": 0.7,
"body": 0.5,
"faq_question": 0.9
},
"note": "全部权重与条目数为工程取值,需按自有样本标定"
}
这里有个细节:把「牙齿美白」放进否定词表,比在排序阶段硬降权更干净。用户搜「洗牙」时,标题写着美白效果的内容本来就不该被召回,这类内容差异属于编辑判断,不是算法能补的。
四、代码段二:上线前校验脚本
映射表常见的错是「列了不用」与「互相打架」:某个 alt 词既挂在等价关系下,又挂在否定词表里;或者配置里写了一堆替代词,站内根本没有任何一条内容用到。下面这段做三项静态校验。
python
import json
from collections import Counter
with open("synonyms.json", encoding="utf-8") as f:
cfg = json.load(f)
errors = []
seen = {}
for i, e in enumerate(cfg["entries"]):
if e.get("relation") not in ("equivalent", "hierarchy",
"related", "negative"):
errors.append(f"entry {i}: unknown relation")
for w in e.get("alt", []):
if w in seen and seen[w] != e["pref"]:
errors.append(f"conflict: {w} -> {seen[w]} / {e['pref']}")
seen[w] = e["pref"]
if not 0.0 <= e.get("boost", 0.0) <= 1.0:
errors.append(f"entry {i}: boost out of range")
# 否定词不得同时作为等价替代词出现
neg = {w for e in cfg["entries"] if e["relation"] == "negative"
for w in e.get("exclude", [])}
equiv = {w for e in cfg["entries"] if e["relation"] == "equivalent"
for w in e.get("alt", [])}
for w in neg & equiv:
errors.append(f"negative+equivalent: {w}")
# 单表条目上限 24 条(工程取值,需按自有样本标定)
if len(cfg["entries"]) > 24:
errors.append("entries exceed cap 24")
print("entries:", len(cfg["entries"]),
"alt words:", len(seen),
"errors:", len(errors))
for e in errors:
print(" -", e)
脚本只做静态检查,动态部分还要接一次真实查询集:把近 200 条站内搜索词(工程取值)跑一遍,看零结果率有没有变化。零结果率下降才算映射生效,配置改了却没有查询集回测,等于没上线。
五、六个坑位
| 坑 | 表现 | 处理 |
|---|---|---|
| 等价表混入上下位 | 搜日常维护却出治疗稿 | 关系类型显式存,层级单独走 |
| 替代词只在后台生效 | 结构化问答里仍是术语 | FAQPage 的 question 用口语写法 |
| 否定词表缺失 | 美白内容被洗牙召回 | 显式维护 exclude |
| 标注与可见内容不一致 | 页面没写却标了问答 | 标记只覆盖页面真实存在的问答 |
| 改配置不回测 | 零结果率没动 | 固定查询集,每次改动跑一遍 |
| 权重写死在代码里 | 调参要发版 | 放进配置,允许按字段覆盖 |
六、发布前自检清单
css
[ ] 每条映射带 relation,等价与层级不混用
[ ] 否定词与等价替代词无交集(校验脚本通过)
[ ] FAQPage 只标记页面可见的问答,question 用口语
[ ] 示例站点、地域统一占位:example.com/示例省/示例市
[ ] 字段权重走配置,不硬编码
[ ] 固定查询集不少于 200 条(工程取值,需按自有样本标定)
[ ] 单表条目上限 24 条、批量任务单批不超过 500 行(工程取值)
[ ] 全部阈值标注「经验取值/需按自有样本标定」
[ ] 文案不含疗效承诺、不含费用数字、不含机构与真实城市名
七、收口
「搜洗牙搜不到洁治」不是检索坏了,是没人为口语和术语之间那层关系负责。把关系类型写出来、把权重放进配置、把校验脚本接进发布流程,这个问题就从「编辑和运维互相猜」变成一条能逐项核对的流水线。
再补一句边界:结构化标注让机器更容易读懂页面在回答什么,但不承诺任何展示位置或流量变化;页面写的是什么,标注就该是什么。把这条守住,映射表才不会变成另一堆没人维护的补丁。
参考资料
- schema.org FAQPage(问答型页面的结构化标记)
- W3C SKOS Simple Knowledge Organization System(prefLabel/altLabel/broader/narrower)
- Google 搜索中心结构化数据文档(标记与页面可见内容一致)
- 《中国居民口腔健康指南》(「洁牙」表述,与内容库「洁治」构成词形差异)
本文使用 AI 辅助整理,经人工审核。