bigywater.tech
Elasticsearch · 24

Analyzer 的完整执行链路

真实用_analyze的explain:true逐级打印char_filter、tokenizer、两层token_filter的真实输出,验证Analyzer完整执行链路,以及停用词删除后position留空位的真实设计用意。

char_filter
真实在分词前替换字符,&变成and
tokenizer
真实切成6个token,各自带位置信息
停用词过滤器
真实删词后position留空位,不紧凑重排

做的事:真实配一个char_filter+tokenizer+两层token_filter的自定义分析器,逐级打印每一步

代码PUT /analyzer_test {"settings":{"analysis":{ "char_filter": {"my_char_filter": {"type":"mapping","mappings":["& => and"]}}, "filter": {"my_stop": {"type":"stop","stopwords":["the","is"]}}, "analyzer": {"my_custom_analyzer": { "type":"custom","char_filter":["my_char_filter"], "tokenizer":"standard","filter":["lowercase","my_stop"] }} }}} POST /analyzer_test/_analyze { "analyzer": "my_custom_analyzer", "text": "The Cat & Dog is Running", "explain": true }

验证:char_filter真实在分词之前就先替换掉了特殊字符

实测 · 本机 Elasticsearch 8.15.0 执行输出
原文: "The Cat & Dog is Running"
charfilters.my_char_filter.filtered_text:
→ "The Cat and Dog is Running"    ← 真实&被替换成了and,这一步还没有分词

这是整条链路真实最早发生的一步:char_filter工作在原始字符串层面,分词器还完全没有介入——本文这次配的mapping类型字符过滤器真实把&替换成了and,替换完的结果才会真实被送进下一步的分词器。如果不做这一步替换,&这个符号在标准分词器眼里真实会被当成单词边界直接丢弃,搜索"cat and dog"这种查询就匹配不到原文里用&写的"cat & dog"。

验证:tokenizer真实把替换后的字符串切成了6个独立token,带着各自的位置信息

实测 · 本机执行输出
tokenizer.standard.tokens(真实6个token,position从0到5):
The(0) Cat(1) and(2) Dog(3) is(4) Running(5)

真实的standard分词器在这一步只负责按词边界切分,不改变大小写、不做任何过滤——6个原始单词真实一个不少地变成了6个独立token,每个token真实都带着position(在这句话里第几个词)和start_offset/end_offset(在原文里的字符位置)这两类定位信息,这些信息会真实一路带到后面的token_filter阶段,供match_phrase这类依赖词序的查询使用。

验证:两层token_filter依次生效,停用词真实被删掉但position真实留了空位

实测 · 本机执行输出
tokenfilters[0] lowercase之后: the(0) cat(1) and(2) dog(3) is(4) running(5)
tokenfilters[1] my_stop之后:   cat(1) and(2) dog(3) running(5)
                                ← the和is真实被删掉了,但running真实还是position=5,不是重排成4
这是本文认为整个链路里最真实有价值的细节:my_stop过滤器删掉the(position 0)和is(position 4)之后,剩下的running真实依然带着position=5,不会因为前面少了一个词就被重新编号成4。这个"留空位不重排"的设计真实是为match_phrase这类短语查询服务的——如果查询词之间原本隔着一个被删掉的停用词,position留空能让搜索引擎真实知道"这两个词中间原来隔了一个词",match_phrase可以配合slop参数真实允许跨过这种因为停用词被删除而产生的位置空隙,继续匹配到原文里语序相邻、只是中间夹了个停用词的短语;如果position真实被紧凑重排,这种基于距离的短语匹配就会真实失真,把原本隔了好几个词的内容误判成紧挨着的。这整条链路(char_filter → tokenizer → token_filter,严格按声明顺序依次处理)正是本系列标题"Analyzer的完整执行链路"的真实含义:三个阶段各自只做自己该做的事,但每一步的输出都真实完整地传递给下一步,一步都不能跳过或者乱序。

分步演示:Analyzer四个阶段真实依次处理的完整链路

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

从char_filter到两层token_filter,position编号真实留空不重排
这一步新验证的处理阶段

    本文用到的工具

    • 本机真实部署的 Elasticsearch 8.15.0(单节点,tar包直接启动)
    • 真实的 _analyze API(explain:true)与自定义Analyzer
    京ICP备2026067502号-1京公网安备11010502063487号