停用词与短语查询 | Elasticsearch: 权威指南 | Elastic
2024-12-21
所有查询中
短语匹配 大约占到5%,但是在慢查询里面它们又占大部分。
短语查询性能相对较差,特别是当短语中包括常用词的时候,如 “To be, or not to be”
短语全部由停用词组成,这是一种极端情况。原因在于几乎需要匹配全量的数据。
在 停用词的两面 停用词的优缺点,中,我们提到移除停用词只能节省倒排索引中的一小部分空间。这句话只部分正确,一个典型的索引会可能包含部分或所有以下数据:
将停用词从索引中移除会节省 词项字典 和 倒排表 里的少量空间,但 位置 和 偏移 是另一码事。位置和偏移数据很容易变成索引大小的两倍、三倍、甚至四倍。
analyzed
字符串字段的位置信息默认是开启的,
所以短语查询能随时使用到它。
词项出现的越频繁,用来存储它位置信息的空间就越多。在一个大的文档集合中,对于那些非常常见的词,它们的位置信息可能占用成百上千兆的空间。
运行一个针对高频词 the
的短语查询可能会导致从磁盘读取好几G的数据。这些数据会被存储到内核文件系统的缓存中,以提高后续访问的速度,这看似是件好事,但这可能会导致其他数据从缓存中被剔除,进一步使后续查询变慢。
这显然是我们需要解决的问题。
我们首先应该问自己:是否真的需要使用短语查询 或 近似查询 ?
答案通常是:不需要。在很多应用场景下,比如说日志,我们需要知道一个词 是否 在文档中(这个信息由倒排表提供)而不是关心词的位置在哪里。或许我们要对一两个字段使用短语查询,但是我们完全可以在其他 analyzed
字符串字段上禁用位置信息。
index_options
参数 允许我们控制索引里为每个字段存储的信息。
可选值如下:
docs
not_analyzed
字符串字段是默认的。
freqs
docs
信息,以及每个词在每个文档里出现的频次。词频是完成TF/IDF 相关度计算的必要条件,但如果只想知道一个文档是否包含某个特定词项,则无需使用它。
positions
docs
、 freqs
、 analyzed
,以及每个词项在每个文档里出现的位置。 这对 analyzed
字符串字段是默认的,但当不需使用短语或近似匹配时,可以将其禁用。
offsets
docs
,freqs
,positions
, 以及每个词在原始字符串中开始与结束字符的偏移信息( postings
highlighter )。这个信息被用以高亮搜索结果,但它默认是禁用的。
我们可以在索引创建的时候为字段设置 index_options
选项,或者在使用 put-mapping
API新增字段映射的时候设置。我们无法修改已有字段的这个设置:
删除停用词是能显著降低位置信息所占空间的一种方式。 一个被删除停用词的索引仍然可以使用短语查询,因为剩下的词的原始位置仍然被保存着,这正如 保持位置(Maintaining Positions) 中看到的那样。 尽管如此,将词项从索引中排除终究会降低搜索能力,这使我们难以区分 Man in the moon 与 Man on the moon 这两个短语。
幸运的是,鱼与熊掌是可以兼得的:请查看 common_grams
过滤器。
官方地址:https://www.elastic.co/guide/cn/elasticsearch/guide/current/stopwords-phrases.html