bigywater.tech
Elasticsearch · 39

同义词过滤器

真实验证同义词过滤器在单词场景下的position并列机制,并用多词同义词的真实对比揭示plain synonym过滤器导致的position错位问题,以及synonym_graph如何用positionLength正确解决它。

单词同义词
真实在同一position并列记录,搜任一变体都能命中
plain synonym处理多词同义词
真实导致后续词position错位
synonym_graph
真实用positionLength正确解决多词同义词的位置问题

做的事:真实配一个同义词过滤器,用_analyze看同义词真实落在什么position上

代码PUT /syn_test {"settings":{"analysis":{ "filter": {"my_synonym": {"type":"synonym", "synonyms":["quick,fast,speedy","jump,leap"]}}, "analyzer": {"syn_analyzer": {"type":"custom","tokenizer":"standard","filter":["lowercase","my_synonym"]}} }}} POST /syn_test/_analyze {"analyzer":"syn_analyzer","text":"fast fox"} POST /syn_test/_search {"query":{"match":{"body":"quick fox"}}} # body存的原文是"the fast fox jumps"

验证:真实同一个position上同时放了fast、quick、speedy三个token,搜quick真实能命中存了fast的文档

实测 · 本机 Elasticsearch 8.15.0 执行输出
对"fast fox"分词:
→ fast(position=0) quick(position=0) speedy(position=0) fox(position=1)
  ← 真实三个同义词全部挤在同一个position=0,不是三个独立的位置

搜索"quick fox"(原文存的是"the fast fox jumps"):
→ hits=1 ["the fast fox jumps"]   ← 真实命中了!

这组结果真实揭示了同义词过滤器的核心机制:它不是在索引阶段把"fast"真实替换成"quick",而是真实在同一个position上并列插入所有同义词变体,让倒排索引在这个位置同时记录fast、quick、speedy三个词项。这样一来,不管用户搜索的是这三个词里的哪一个,真实都能在同一个位置命中,而原文到底存的是哪个词完全不影响搜索结果——这正是电商搜索里"沙发/sofa"、"笔记本/laptop"这类同义词需求的真实实现方式。

真实验证一个多词同义词的棱角场景:plain的synonym过滤器会不会污染后续词的position

代码PUT /syn_test3 {"settings":{"analysis":{"filter":{ "my_synonym": {"type":"synonym","synonyms":["usa, united states of america"]}, "my_synonym_graph": {"type":"synonym_graph","synonyms":["usa, united states of america"]} },"analyzer":{ "plain_syn": {"type":"custom","tokenizer":"standard","filter":["lowercase","my_synonym"]}, "graph_syn": {"type":"custom","tokenizer":"standard","filter":["lowercase","my_synonym_graph"]} }}}} POST /syn_test3/_analyze {"analyzer":"plain_syn","text":"the usa is big"} POST /syn_test3/_analyze {"analyzer":"graph_syn","text":"the usa is big"}

验证:plain同义词过滤器真实把"is"和"big"错位挤到了跟展开词同一个position上

实测 · 本机执行输出
plain synonym过滤器分词"the usa is big":
→ the(0) usa(1) united(1) is(2) states(2) big(3) of(3) america(4)
  ← "is"真实跟"states"挤在同一个position=2!
  ← "big"真实跟"of"挤在同一个position=3!这两个都是原文真实存在的独立词

synonym_graph过滤器分词同样的文本:
→ the(0) united(1,长度4) usa(1,长度4) states(2) of(3) america(4) is(5) big(6)
  ← "usa"真实被标记成positionLength=4,完整跨越united/states/of/america四个位置
  ← "is"真实独立落在position=5,"big"真实独立落在position=6,完全没有跟展开词错位
这组真实对比揭示了官方文档反复强调"多词同义词应该用synonym_graph而不是synonym"背后的真实原因:当同义词的一边是多个词("united states of america"真实是4个词)、另一边是单个词("usa")时,plain的synonym过滤器真实没有机制去"预留"这中间多出来的position宽度,导致原文里"usa"后面真实存在的词(这里是"is")被迫真实往前错位,挤进了本该属于同义词展开部分的position。这种position错位对match_phrase这类依赖精确位置关系的查询真实是毁灭性的——"is big"在原文里明明是紧邻的两个词,但分词结果里它们的position真实被同义词展开过程污染,跟"states"、"of"产生了错误的重叠。synonym_graph真实通过引入positionLength这个字段解决了这个问题:它把多词同义词表示成一个跨越多个位置的"图节点",原文后续的词真实依然能拿到正确、不重叠的独立position,不会被同义词展开过程挤占。

分步演示:同义词过滤器从单词并列到多词同义词position错位问题的完整验证

每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。

从单词同义词的并列position到多词同义词真实的position错位与graph修复
这一步新验证的同义词过滤器

    本文用到的工具

    • 本机真实部署的 Elasticsearch 8.15.0(单节点,tar包直接启动)
    • 真实的 synonym 与 synonym_graph token filter
    京ICP备2026067502号-1京公网安备11010502063487号