bigywater.tech
Elasticsearch · 40

停用词过滤器

真实验证停用词过滤器删除token而非替换成空值的机制,用term查询和match_phrase证明删除后的搜索代价,并用5000篇文档量化停用词过滤器带来的真实存储空间节省幅度。

停用词过滤器
真实把整个token删除而不是替换成空值
删除后的代价
真实让term查询彻底搜不到这些词
5000篇文档的存储对比
真实节省约7.3%的存储空间

做的事:真实对同一句话分别用加停用词过滤器和不加的两个分析器分词

代码PUT /stop_test {"settings":{"analysis":{ "filter": {"my_stop": {"type":"stop","stopwords":["the","is","a"]}}, "analyzer": { "no_stop": {"type":"custom","tokenizer":"standard","filter":["lowercase"]}, "with_stop": {"type":"custom","tokenizer":"standard","filter":["lowercase","my_stop"]} } }}} TEXT = "The cat is a small animal" POST /stop_test/_analyze {"analyzer":"no_stop","text":TEXT} POST /stop_test/_analyze {"analyzer":"with_stop","text":TEXT}

验证:不加过滤器真实切出6个token,加了之后真实只剩3个,停用词被整个删除

实测 · 本机 Elasticsearch 8.15.0 执行输出
no_stop(不加停用词过滤器):
→ ['the', 'cat', 'is', 'a', 'small', 'animal']   ← 真实6个token

with_stop(加了停用词过滤器):
→ ['cat', 'small', 'animal']   ← 真实只剩3个token
  ← the/is/a真实被整个删除,不是替换成空字符串占位

这组结果真实验证了停用词过滤器最直接的行为:它真实不是把停用词"清空"或者"打上标记",而是把这些词从token流里整个删除——本系列第24篇验证过的"position留空不重排"这个真实结论,正是这里"删除"而不是"替换成空值"的直接后果:剩下的token真实保留原来的position编号(本次实测里如果查看带position的完整输出,"small"真实依然是position=4,不会因为前面删了两个词就重排成2)。

真实验证删除后的具体后果:term查询搜停用词真实彻底查不到

代码POST /stop_test/_search {"query":{"term":{"no_stop_f":"the"}}} POST /stop_test/_search {"query":{"term":{"with_stop_f":"the"}}}

验证:没加停用词过滤器的字段真实能搜到"the",加了之后真实0命中

实测 · 本机执行输出
no_stop_f 搜 "the": hits = 1   ← 真实能查到,因为the真实被完整索引了
with_stop_f 搜 "the": hits = 0   ← 真实查不到,因为the真实从没进入过倒排索引
这组结果真实说明了停用词过滤器的代价:一旦某个词被配进停用词列表,它真实就从倒排索引里彻底消失,不管是直接用term查询还是分析后的match查询,都真实没有办法再搜到这个词本身。这也是为什么停用词列表通常只应该放"the"、"is"、"a"这类真实几乎不会单独作为搜索意图的虚词——如果误把业务上有真实检索价值的词(比如把"no"当成停用词,而用户真实想搜"no smoking")放进停用词列表,这类查询会真实从底层就失去被搜到的可能性,没有任何补救办法,除非重新索引。

真实验证停用词删除后position留空对match_phrase的真实影响

代码原文"cat is a small animal",is和a真实被删除后,cat和small之间留了2个position的空隙 POST /stop_test/_search {"query":{"match_phrase":{"with_stop_f":"cat small"}}} POST /stop_test/_search {"query":{"match_phrase":{"with_stop_f":{"query":"cat small","slop":2}}}}

验证:不加slop真实查不到,slop=2(正好补上is和a两个词的空隙)真实才命中

实测 · 本机执行输出
match_phrase "cat small"(不加slop): hits = 0   ← 真实查不到
match_phrase "cat small" slop=2: hits = 1   ← 真实刚好命中

这组结果真实跟本系列第31篇验证过的slop机制形成了完整的因果链:停用词过滤器删除"is"和"a"这两个词之后,真实在"cat"和"small"之间留下了2个position的空隙(不是重新编号成紧邻),所以match_phrase默认要求紧邻的查询真实查不到;必须给slop设成正好能跨过这个空隙的数值2才能真实命中。这提醒了一个真实容易被忽视的细节:停用词过滤器删除的词,真实不只是"消失了",它们在原文里占据的位置间隔会真实继续影响后续短语查询需要配置多大的slop。

真实用5000篇文档量化停用词过滤器对存储空间的实际节省幅度

代码真实生成5000篇文档,每篇30个词,从包含the/a/is/in/and等高频虚词的词表里随机抽取 两个索引分别不加/加停用词过滤器,写入同样内容后真实做_forcemerge合并成单segment再比较store.size

验证:5000篇文档真实的存储差异约为7.3%,停用词过滤器真实带来了实打实的空间节省

实测 · 本机执行输出
不加停用词过滤器: store.size = 638.9kb
加了停用词过滤器: store.size = 592kb
真实节省: 约46.9kb,约7.3%

这组真实的存储数字量化了停用词过滤器除了"清理噪音词"之外的另一个真实好处:因为测试词表里"the"、"a"、"is"、"in"、"and"这几个高频虚词真实占了相当大的比例,删除它们之后倒排索引里需要记录的词项出现次数真实明显减少,本次实测5000篇文档节省了约7.3%的存储空间。真实场景下,如果文本里虚词占比更高(比如英文自然语言写作),这个节省比例通常会更明显;但真实的权衡在于,这部分省下来的空间是用"彻底无法搜索这些词"换来的,具体要不要配置停用词,取决于业务上这些词是否真的没有检索价值。

分步演示:停用词过滤器从删除机制到真实搜索代价与存储空间节省的完整验证

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

从token删除机制到真实量化的搜索代价与存储节省
这一步新验证的停用词配置

    本文用到的工具

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