停用词

停用词 #

停用词(Stopwords)是指在大多数文本中非常常见、对区分文档贡献很小的词,例如 theandis。早期信息检索系统会大量使用停用词来减少索引体积;在今天,更需要从 性能与表达力 两方面权衡。

高频词与低频词 #

从词项频率的角度,我们可以把词项粗略分为两类:

  • 低频词(更重要):在文档集合中出现较少,通常信息量更大,区分能力更强
  • 高频词(次重要):在大量文档中都出现,对区分能力弱,但会显著影响性能

哪些词是“高频”,强依赖你的语料:在英文语料里 the 极常见;在中文语料里它反而不会出现。

停用词的优缺点 #

优点:性能 #

假设一个索引有 100 万文档,词 fox 只出现在 20 个文档中:

  • 查询 fox:只需要对很少的候选文档计算 _score
  • 查询 the OR fox:由于 the 几乎在所有文档里都出现,系统可能需要对大量文档计算 _score,代价骤增

因此,减少极高频词对候选集合的“污染”,有助于控制查询成本。

缺点:表达力下降 #

把常见词一律移除会让一些真实需求变得难以表达:

  • 区分 happynot happy
  • 搜索乐队名 The The
  • 搜索名句 “to be, or not to be”
  • 某些短词在特定语料里可能很关键(例如国家代码、产品型号)

在现代硬件条件下,“省空间”往往不再是使用停用词的主理由;更重要的是避免让搜索变得“说不清、搜不准”。

如何配置停用词 #

停用词由 stop 过滤器处理,也可以通过分析器参数直接配置。

为 standard 分析器指定停用词 #

PUT /my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "type": "standard",
          "stopwords": [ "and", "the" ]
        }
      }
    }
  }
}

使用语言分析器的默认停用词表 #

语言分析器通常会内置适合该语言的停用词列表,例如:

PUT /my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_english": {
          "type": "english",
          "stopwords": "_english_"
        }
      }
    }
  }
}

如需禁用停用词,可使用 _none_(示意):

{
  "type": "english",
  "stopwords": "_none_"
}

从文件加载停用词 #

{
  "type": "english",
  "stopwords_path": "stopwords/english.txt"
}

要点:

  • 文件需要存在于每个节点上(路径相对于配置目录)
  • 更新文件后,需要通过“关闭并重新打开索引”或“滚动重启节点”等方式让分析器重新加载
  • 更新停用词只影响后续分析/查询;已索引的数据若要生效通常需要重建索引

为什么短语查询特别怕高频词 #

短语查询需要依赖**位置(positions)**数据:词在文档中的顺序与位置会被存储起来。高频词在大量文档里出现,会产生巨量的位置信息:

  • 一个包含常用词(如 the)的短语查询,可能需要读取大量 positions 数据
  • 这些数据会强烈影响磁盘读取与系统缓存,进而拖慢其他查询

这也是为什么在慢查询中,短语类查询(尤其包含高频词)常常占比很高。

不用“删词”也能控制性能 #

现代实践中,很多系统倾向于少用或不用停用词,而是通过查询策略减少“只命中常用词”的候选集合,例如:

1)operator: and #

{
  "match": {
    "text": {
      "query": "the quick brown fox",
      "operator": "and"
    }
  }
}

2)minimum_should_match #

{
  "match": {
    "text": {
      "query": "the quick brown fox",
      "minimum_should_match": "75%"
    }
  }
}

这类做法的核心是:让“更重要的词”主导候选集合,把高频词更多用于评分区分,而不是让它们把候选集合撑爆。

常用词项分治:cutoff_frequency(来自权威指南的思路) #

权威指南提供了一个实用思路:把查询词拆成“低频(更重要)”与“高频(次重要)”两组。match 查询的 cutoff_frequency 可以用于这个分治:

{
  "match": {
    "text": {
      "query": "quick and the dead",
      "cutoff_frequency": 0.01
    }
  }
}

直觉效果:

  • 低频词参与匹配(决定候选集)
  • 高频词更多参与评分(在候选集内部区分更相关的结果)

说明:cutoff_frequency 与部分“常用词项查询”能力在不同产品/版本中的支持情况可能不同,你可以把它视为一种“分治策略”的参考:核心目标是避免高频词让候选集合与评分成本失控。

小结 #

  • 停用词的主要价值是性能,但代价是表达力下降
  • 高并发与短语查询场景里,高频词的 positions 数据可能成为主要性能瓶颈
  • 现代系统中,常见做法是少用停用词,转而用 operator: andminimum_should_match、分治策略来控制成本
  • 如果要用停用词,建议从“领域高频词/噪声词”入手,谨慎、可回滚地迭代

下一步可以继续阅读:

参考手册(API 与参数) #