3.3 Elasticsearch-同义词、拼写纠错、Suggesters(term/phrase/completion)

在这里插入图片描述

3.3 Elasticsearch-同义词、拼写纠错、Suggesters(term/phrase/completion)

1. 同义词(Synonyms)

同义词功能让“土豆≈马铃薯≈potato”这类映射在检索层生效,避免用户因为用词差异而漏掉文档。Elasticsearch 支持两种生效位置:

  • 索引时(index-time):在 analyzer 里放 synonym filter,写入前就把原文替换成统一词形。优点是查询快、倒排里直接命中;缺点是索引体积膨胀、同义词表变更必须重建索引。
  • 查询时(search-time):给查询串单独配一个 search_analyzer,只在查询阶段展开同义词。索引体积不变,词表可随时热更新;代价是每次查询都要做一遍展开,QPS 高时 CPU 压力明显。

官方推荐“查询时展开”+“同义词过滤器缓存”的组合:

PUT /product
{
  "settings": {
    "analysis": {
      "filter": {
        "my_synonym": {
          "type": "synonym",
          "synonyms_path": "analysis/synonym.txt",
          "updateable": true          // 7.3+ 支持热更新
        }
      },
      "analyzer": {
        "synonym_analyzer": {
          "tokenizer": "ik_max_word",
          "filter": ["lowercase", "my_synonym"]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "ik_max_word",
        "search_analyzer": "synonym_analyzer"
      }
    }
  }
}

synonym.txt 示例:

土豆,马铃薯,potato

注意

  • 多词同义词必须放在同一行,用英文逗号分隔;如果写成两行,ES 会当成双向同义,导致“土豆”也展开成“马铃薯 potato”,可能误召回。
  • 查询时展开会把同义词当 OR 处理,默认 bool should 语义,可通过 tie_breaker 调整权重。
  • 若使用 IK 分词,务必保证同义词过滤器在 IK 之后,否则“土豆”还没被切出来就替换,会失效。
2. 拼写纠错(Spell Check)

ES 没有独立的“spellcheck” API,而是借助 suggester 里的 term 模式完成纠错。核心思路:把用户输入的每个词与索引里实际出现的词做编辑距离(Levenshtein)比对,返回距离 ≤ max_edits(默认 2)且词频 ≥ min_doc_freq 的候选。

POST /product/_search
{
  "suggest": {
    "spell-check": {
      "text": "马铃署",
      "term": {
        "field": "title",
        "string_distance": "internal",   // 可选 ngram、levenshtein、jarowinkler
        "max_edits": 2,
        "min_doc_freq": 2,
        "sort": "frequency"
      }
    }
  }
}

返回示例:

"suggest": {
  "spell-check": [
    {
      "text": "马铃署",
      "offset": 0,
      "length": 3,
      "options": [
        { "text": "马铃薯", "score": 0.89, "freq": 314 },
        { "text": "马铃鼠", "score": 0.71, "freq": 5 }
      ]
    }
  ]
}

拿到候选后,前端可提示“您是不是要找:马铃薯”。

3. Suggesters 三兄弟

ES 把“建议”抽象成三种模式,各自有适用场景:

类型工作级别数据来源实时性典型场景
term词粒倒排索引实时拼写纠错
phrase短语粒倒排+Shingle实时整句纠错(“elasticsearh”→“elasticsearch”)
completion前缀粒独立的 in-memory FST实时搜索框自动补全(“el”→“elasticsearch”)
3.1 term suggester

已在上节演示。只纠错,不补全;返回单个词候选。

3.2 phrase suggester

在 term 基础上加 n-gram 语言模型,对整句打分,能纠正“空格打错”“词序颠倒”等跨词错误。

POST /product/_search
{
  "suggest": {
    "phrase-check": {
      "text": "elasticsearh 同义词",
      "phrase": {
        "field": "title.trigram",   // 需提前用 shingle filter 生成 trigram 字段
        "max_errors": 0.8,
        "confidence": 2.0,
        "highlight": {
          "pre_tag": "<em>",
          "post_tag": "</em>"
        }
      }
    }
  }
}

返回:

"options": [
  {
    "text": "elasticsearch <em>同义词</em>",
    "highlighted": "elasticsearch <em>同义词</em>",
    "score": 0.92
  }
]

注意

  • title.trigram 需用 shingle filter 生成 2-3 词滑动窗口,否则语言模型无数据。
  • confidence 越高,候选越少;max_errors 表示允许句子中最多有多大比例被纠错,默认 1.0(全句可改)。
3.3 completion suggester

专为“边输入边提示”设计,数据结构是内存里的 FST(Finite State Transducer),前缀查询复杂度 O(k)(k 为前缀长度),毫秒级返回。

PUT /product
{
  "mappings": {
    "properties": {
      "title": {
        "type": "completion",       // 独立字段类型
        "analyzer": "ik_max_word",
        "preserve_separators": true,
        "preserve_position_increments": true,
        "max_input_length": 50
      }
    }
  }
}

写入:

POST /product/_doc/1
{
  "title": ["Elasticsearch 同义词", "ES 同义词设置"]
}

查询:

POST /product/_search
{
  "suggest": {
    "completion-sug": {
      "prefix": "es 同",
      "completion": {
        "field": "title",
        "size": 5,
        "fuzzy": {
          "fuzziness": 1            // 允许前缀也模糊
        }
      }
    }
  }
}

返回:

"options": [
  { "text": "ES 同义词设置", "_score": 1.0 },
  { "text": "Elasticsearch 同义词", "_score": 0.8 }
]

进阶玩法

  • context 做分类过滤,比如只提示“手机”类目下的品牌。
  • 结合 payload 回传商品 ID、价格,前端直接渲染,无需二次查询。
  • 7.x 之后支持 可搜索快照 里的 completion,FST 可以落盘到快照,集群重启不再重建,冷启动时间从分钟级降到秒级。
4. 运维与性能
  • 同义词热更新:7.3+ 的 updateable=true 只对 search-time 生效,文件变更后调用 _reload_search_analyzers 即可,无需滚动重启。
  • completion 内存占用:FST 大小 ≈ 索引唯一词项数 × 平均长度 × 1.5 byte,1000 万中文词约 2 GB。若数据量过大,可拆分成多索引 + alias,或改用 search-as-you-type 字段(内部是 shingle + prefix query,内存友好但 latency 稍高)。
  • phrase suggester 的 shard 级局部模型:默认只在协调节点合并候选,跨 shard 时可能打分不准。可设置 ?preference=_local 让查询落到同一 shard,提升一致性。
5. 小结
  • 同义词:优先“查询时展开”,词表走文件 + reload_search_analyzers 热更新。
  • 拼写纠错:term suggester 做单词,phrase suggester 做整句,均需提前构造 shingle 字段。
  • 自动补全:completion suggester 基于内存 FST,最快;数据量大时考虑 search-as-you-type 或分层索引。
  • 三者可以组合成“输入-纠错-补全-同义展开”的完整链路,让用户“打错也能搜到,打一半就能提示,提示的还是同义词扩展后的结果”。
    更多技术文章见公众号: 大城市小农民
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乔丹搞IT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值