身安不如心安,屋宽不如心宽 。

取消某个索引与别名的关联关系

tacsklet 回复了问题 • 3 人关注 • 2 个回复 • 1907 次浏览 • 2020-08-14 09:44 • 来自相关话题

es sort和rescore问题

回复

zhangdadadapao 发起了问题 • 2 人关注 • 0 个回复 • 3323 次浏览 • 2020-08-14 09:44 • 来自相关话题

ELK elasticsearch搜索报错

回复

xiao_peng 发起了问题 • 1 人关注 • 0 个回复 • 1113 次浏览 • 2020-08-13 14:44 • 来自相关话题

index分片数量均衡,但主分片分配不均

zxsapple 回复了问题 • 3 人关注 • 4 个回复 • 1314 次浏览 • 2020-08-13 13:35 • 来自相关话题

elasticsearch 7.0版本 docker下 es集群搭建问题

Charele 回复了问题 • 2 人关注 • 1 个回复 • 1814 次浏览 • 2020-08-13 10:49 • 来自相关话题

es in查询超时问题

pony_maggie 回复了问题 • 5 人关注 • 3 个回复 • 2191 次浏览 • 2020-08-12 16:00 • 来自相关话题

6.7.2版本es的脚本排序在循环数组时与想象中不一样

luman 回复了问题 • 2 人关注 • 2 个回复 • 1449 次浏览 • 2020-08-12 14:39 • 来自相关话题

Observability: 如何为 APM 定制 transactions 及 spans

回复

liuxg 发起了问题 • 1 人关注 • 0 个回复 • 1225 次浏览 • 2020-08-12 10:17 • 来自相关话题

如果一个query查询出若干条数据, 但是我只想从第n条到第m条数据求和, 能用聚合分析吗?我该怎么操作?求大神指点

pony_maggie 回复了问题 • 2 人关注 • 1 个回复 • 1518 次浏览 • 2020-08-12 10:05 • 来自相关话题

es 内存泄漏?查询线程内存占用越来越大

laoyang360 回复了问题 • 5 人关注 • 5 个回复 • 2596 次浏览 • 2020-08-11 18:58 • 来自相关话题

数据模型选择问题,同步更新性能方面问题

回复

aw 发起了问题 • 1 人关注 • 0 个回复 • 1094 次浏览 • 2020-08-11 17:06 • 来自相关话题

ES如何更新数组中某一个字段的值

flytogo 回复了问题 • 3 人关注 • 3 个回复 • 20989 次浏览 • 2020-08-11 15:46 • 来自相关话题

是否可以自己制造es的底层数据

Charele 回复了问题 • 2 人关注 • 1 个回复 • 1524 次浏览 • 2020-08-11 11:14 • 来自相关话题

es on k8s集群上的ssl认证有时间限制,这个大家是怎么处理的

回复

zmc 发起了问题 • 1 人关注 • 0 个回复 • 1349 次浏览 • 2020-08-10 19:18 • 来自相关话题

​2. ES之从零开始 | 纠错(Did You Mean)

Ricky_Lau 发表了文章 • 1 个评论 • 4713 次浏览 • 2020-08-10 17:43 • 来自相关话题

2. ES之从零开始 - 纠错(Did You Mean)

纠错的另一种说法叫拼写检查(Spell Check),降低由于输入错误导致的不好检索体验。
本文将会分享此类问题的ES解决方案,致力于提升用户的体验。

简单的约定(Simple Convention)

  • ES
  • Version
  • 7.8.0
  • Analyzer(index、query)
  • Ansj
  • 测试数据
  • 2020年中国营收Top500公司的名称

  • ES纠错测试数据构建
  • [点我,查看创建测试索引的DSL](https://github.com/RickyLau/es ... _index)
  • [点我,查询测试数据初始化DSL](https://github.com/RickyLau/es ... u_mean)

    词纠错(Term Suggester)

    Elasticsearch通过直接读取Lucene的词库(Term Dictionary)数据并通过莱文斯坦距离(Levenshtein Distance)算法来提供纠错功能。

    1. 模拟拼写错误,发送纠错请求
  • analyzer, 默认采用指定字段的search analzyer, 为了把搜索词当成一个整体,采用了keywrok analyzer.

    <br /> GET top500_company_names/_search<br /> {<br /> "suggest": {<br /> "my_suggestion": {<br /> "text": "有钱公司",<br /> "term": {<br /> "field": "name",<br /> "analyzer": "keyword"<br /> }<br /> }<br /> }<br /> }<br />

    1. 根据拼写错误的关键词,获取纠错词
  • options 纠错词列表,获取词库中满足条件的词(默认的最大编辑距离为2,max_edits: 2)
  • score, 编辑距离越短得分越高。
  • freq, lucene 词库中出现的频率。

    <br /> {<br /> "my_suggestion" : [<br /> {<br /> "text" : "有钱公司",<br /> "offset" : 0,<br /> "length" : 4,<br /> "options" : [<br /> {<br /> "text" : "有限公司",<br /> "score" : 0.75,<br /> "freq" : 421<br /> }<br /> ]<br /> }<br /> ]<br /> }<br />
    1. 中文不像英文单词那么长,2个字以前都是有出错概率的
  • 期望输入太平,结果输成了太苹

    <br /> GET top500_company_names/_search<br /> {<br /> "suggest": {<br /> "my_suggestion": {<br /> "text": "太苹",<br /> "term": {<br /> "field": "name",<br /> "analyzer": "keyword"<br /> }<br /> }<br /> }<br /> }<br />
    1. Demo 3的纠错请求结果
      <br /> {<br /> "my_suggestion" : [<br /> {<br /> "text" : "太苹",<br /> "offset" : 0,<br /> "length" : 2,<br /> "options" : [ ]<br /> }<br /> ]<br /> }<br /> <br />
    2. 原来是两个参数限制了结果的返回
  • min_word_length, 表示只有当关键词长度大于等于该值时,才会进行纠错
  • suggest_mode, 默认只有当搜索词在词库中不存在时,再会进行纠错
  • missing, 搜索词不存在于词库中,执行搜索逻辑(默认)
  • popular, 只返回频率大于原始词的纠错词
  • always, 始终返回任何命中的纠错词

    <br /> GET top500_company_names/_search<br /> {<br /> "suggest": {<br /> "my_suggestion": {<br /> "text": "太苹",<br /> "term": {<br /> "field": "name",<br /> "suggest_mode": "always",<br /> "min_word_length": 2,<br /> "analyzer": "keyword"<br /> }<br /> }<br /> }<br /> }<br />

    1. 两个字纠错结果
      <br /> {<br /> "my_suggestion" : [<br /> {<br /> "text" : "太苹",<br /> "offset" : 0,<br /> "length" : 2,<br /> "options" : [<br /> {<br /> "text" : "太原",<br /> "score" : 0.5,<br /> "freq" : 1<br /> },<br /> {<br /> "text" : "太平",<br /> "score" : 0.5,<br /> "freq" : 1<br /> },<br /> {<br /> "text" : "太极",<br /> "score" : 0.5,<br /> "freq" : 1<br /> }<br /> ]<br /> }<br /> ]<br /> }<br />

    2. suggest_mode 之always
      <br /> GET top500_company_names/_search<br /> {<br /> "suggest": {<br /> "my_suggestion": {<br /> "text": "太平",<br /> "term": {<br /> "field": "name",<br /> "suggest_mode": "always",<br /> "min_word_length": 2,<br /> "analyzer": "keyword"<br /> }<br /> }<br /> }<br /> }<br />

    3. suggest_mode 之always 结果
  • 返回了所有命中的纠错词

    <br /> {<br /> "my_suggestion" : [<br /> {<br /> "text" : "太平",<br /> "offset" : 0,<br /> "length" : 2,<br /> "options" : [<br /> {<br /> "text" : "太平洋",<br /> "score" : 0.5,<br /> "freq" : 2<br /> },<br /> {<br /> "text" : "太原",<br /> "score" : 0.5,<br /> "freq" : 1<br /> },<br /> {<br /> "text" : "太极",<br /> "score" : 0.5,<br /> "freq" : 1<br /> }<br /> ]<br /> }<br /> ]<br /> }<br />

    1. suggest_mode 之popular
      <br /> GET top500_company_names/_search<br /> {<br /> "suggest": {<br /> "my_suggestion": {<br /> "text": "太平",<br /> "term": {<br /> "field": "name",<br /> "suggest_mode": "popular",<br /> "min_word_length": 2,<br /> "analyzer": "keyword"<br /> }<br /> }<br /> }<br /> }<br />

    2. suggest_mode 之popular结果
  • 太平在词库中 出现过1次
  • popular 应该返回频率大于1的纠错词

    <br /> {<br /> "my_suggestion" : [<br /> {<br /> "text" : "太平",<br /> "offset" : 0,<br /> "length" : 2,<br /> "options" : [<br /> {<br /> "text" : "太平洋",<br /> "score" : 0.5,<br /> "freq" : 2<br /> }<br /> ]<br /> }<br /> ]<br /> }<br />

    1. 通过编辑距离控制纠错词列表
  • max_edits, 通过编辑距离在词库中获取建议词,该值只能为1和2,设置其它值则会报错,默认距离为2.
  • 编辑距离为1时,召回搜索词与词库中只错一个字符的词。

    <br /> GET top500_company_names/_search<br /> {<br /> "suggest": {<br /> "my_suggestion": {<br /> "text": "太平",<br /> "term": {<br /> "field": "name",<br /> "suggest_mode": "always",<br /> "min_word_length": 2,<br /> "analyzer": "keyword",<br /> "max_edits": 1<br /> }<br /> }<br /> }<br /> }<br />
    1. 通过编辑距离控制纠错词列表结果
      <br /> {<br /> "my_suggestion" : [<br /> {<br /> "text" : "太平",<br /> "offset" : 0,<br /> "length" : 2,<br /> "options" : [<br /> {<br /> "text" : "太平洋",<br /> "score" : 0.5,<br /> "freq" : 2<br /> },<br /> {<br /> "text" : "太原",<br /> "score" : 0.5,<br /> "freq" : 1<br /> },<br /> {<br /> "text" : "太极",<br /> "score" : 0.5,<br /> "freq" : 1<br /> }<br /> ]<br /> }<br /> ]<br /> }<br />

    2. 纠错词的排序与返回个数
  • size, 每个词返回的最大纠错词
  • sort, 返回纠错词的顺序
  • score, 三层排序,先根据编辑距离得分倒序,再根据纠错词频率倒序,最后纠错词的字典序
  • frequency, 三层排序,先根据纠错词频率倒序,再根据编辑距离得分倒序,最后纠错词的字典序

    <br /> GET top500_company_names/_search<br /> {<br /> "suggest": {<br /> "my_suggestion": {<br /> "text": "太平",<br /> "term": {<br /> "field": "name",<br /> "suggest_mode": "always",<br /> "min_word_length": 2,<br /> "analyzer": "keyword",<br /> "size": 2,<br /> "sort": "score"<br /> }<br /> }<br /> }<br /> }<br />

    1. 纠错词的排序与返回个数结果
      <br /> {<br /> "my_suggestion" : [<br /> {<br /> "text" : "太平",<br /> "offset" : 0,<br /> "length" : 2,<br /> "options" : [<br /> {<br /> "text" : "太平洋",<br /> "score" : 0.5,<br /> "freq" : 2<br /> },<br /> {<br /> "text" : "太原",<br /> "score" : 0.5,<br /> "freq" : 1<br /> }<br /> ]<br /> }<br /> ]<br /> }<br /> }<br />


    2. 编辑距离与得分
  • internal, 距离越小得分越高。
  • jaro_winkler JW算法 ,在internal 基本上也考虑了通用的前缀的加权逻辑。

    <br /> GET top500_company_names/_search<br /> {<br /> "suggest": {<br /> "my_suggestion": {<br /> "text": "太平",<br /> "term": {<br /> "field": "name",<br /> "suggest_mode": "always",<br /> "min_word_length": 2,<br /> "analyzer": "keyword",<br /> "string_distance": "jaro_winkler"<br /> }<br /> }<br /> }<br /> }<br />

    1. 编辑距离与得分结果
  • 太平洋和太原编辑距离都是1
  • internal 都是0.5分,相同的编辑距离
  • jaro_winkler 太平洋得分要远高于太原,因为太平洋在词库中有一个通用的前缀太平

    <br /> {<br /> "my_suggestion" : [<br /> {<br /> "text" : "太平",<br /> "offset" : 0,<br /> "length" : 2,<br /> "options" : [<br /> {<br /> "text" : "太平洋",<br /> "score" : 0.9111111,<br /> "freq" : 2<br /> },<br /> {<br /> "text" : "太原",<br /> "score" : 0.6666667,<br /> "freq" : 1<br /> },<br /> {<br /> "text" : "太极",<br /> "score" : 0.6666667,<br /> "freq" : 1<br /> }<br /> ]<br /> }<br /> ]<br /> }<br />

    1. 通过纠错词最小文档阀值限制返回的个数
  • min_doc_freq, 纠错词最小文档阀值,类型可为数值和百分比。

    <br /> GET top500_company_names/_search<br /> {<br /> "suggest": {<br /> "my_suggestion": {<br /> "text": "福地",<br /> "term": {<br /> "field": "name",<br /> "suggest_mode": "always",<br /> "min_word_length": 2,<br /> "analyzer": "keyword",<br /> "size": 20,<br /> "min_doc_freq":3<br /> }<br /> }<br /> }<br /> }<br />

    1. 通过纠错词频率限制控制返回的个数
      <br /> {<br /> "my_suggestion" : [<br /> {<br /> "text" : "福地",<br /> "offset" : 0,<br /> "length" : 2,<br /> "options" : [<br /> {<br /> "text" : "福建",<br /> "score" : 0.5,<br /> "freq" : 4<br /> }<br /> ]<br /> }<br /> ]<br /> }<br />

    2. 第一个字错了,可以纠正么?
      <br /> GET top500_company_names/_search<br /> {<br /> "suggest": {<br /> "my_suggestion": {<br /> "text": "大平洋",<br /> "term": {<br /> "field": "name",<br /> "suggest_mode": "always",<br /> "min_word_length": 2,<br /> "analyzer": "keyword"<br /> }<br /> }<br /> }<br /> }<br />

    3. 第一个字错了,在上述语法中无法正常纠正
      <br /> {<br /> "my_suggestion" : [<br /> {<br /> "text" : "大平洋",<br /> "offset" : 0,<br /> "length" : 3,<br /> "options" : [ ]<br /> }<br /> ]<br /> }<br />

    4. 第一个字错了的正确纠正DSL
  • prefix_length, 只纠正满足前缀条件的搜索词,默认值为1

    <br /> GET top500_company_names/_search<br /> {<br /> "suggest": {<br /> "my_suggestion": {<br /> "text": "大平洋",<br /> "term": {<br /> "field": "name",<br /> "suggest_mode": "always",<br /> "min_word_length": 2,<br /> "analyzer": "keyword",<br /> "prefix_length": 0<br /> }<br /> }<br /> }<br /> }<br />

    1. 第一个字错了的正确纠正结果
      <br /> {<br /> "my_suggestion" : [<br /> {<br /> "text" : "大平洋",<br /> "offset" : 0,<br /> "length" : 3,<br /> "options" : [<br /> {<br /> "text" : "太平洋",<br /> "score" : 0.6666666,<br /> "freq" : 2<br /> },<br /> {<br /> "text" : "平洋",<br /> "score" : 0.5,<br /> "freq" : 2<br /> }<br /> ]<br /> }<br /> ]<br /> }<br />

    2. suggest计算是分片级的,而最终的TOP K 可能会出现频率统计精度丢失,可以通过shard_size来修正
      <br /> GET top500_company_names/_search<br /> {<br /> "suggest": {<br /> "my_suggestion": {<br /> "text": "大平洋",<br /> "term": {<br /> "field": "name",<br /> "suggest_mode": "always",<br /> "min_word_length": 2,<br /> "analyzer": "keyword",<br /> "prefix_length": 0,<br /> "shard_size": 10<br /> }<br /> }<br /> }<br /> }<br />

    3. 公司名称纠错
      <br /> GET top500_company_names/_search<br /> {<br /> "suggest": {<br /> "my_suggestion": {<br /> "text": "华侨集团有限公司",<br /> "term": {<br /> "field": "name",<br /> "suggest_mode": "always"<br /> }<br /> }<br /> }<br /> }<br />

    4. 公司名称纠错结果
  • 通常公司名称都是分词字段,使用默认 search_analyzer或者 keyword analyzer 都无法针对完整公司名纠错。

    <br /> {<br /> "my_suggestion" : [<br /> {<br /> "text" : "华侨",<br /> "offset" : 0,<br /> "length" : 2,<br /> "options" : [ ]<br /> },<br /> {<br /> "text" : "集团",<br /> "offset" : 2,<br /> "length" : 2,<br /> "options" : [ ]<br /> },<br /> {<br /> "text" : "有限公司",<br /> "offset" : 4,<br /> "length" : 4,<br /> "options" : [ ]<br /> }<br /> ]<br /> }<br />



    短语纠错(Phrase Suggester)

    多个词组合成一个整体进行拼写错误纠错。

    1. 短语纠错 查询
  • direct_generator, 短语纠错词生成器,生成器主要是用于多个词组合并输出得分。
  • 生成器,内部的参数与词纠错一致。
  • max_errors, 只允许纠错 max_errors个词
  • highlight, 纠错词高亮
  • collate, 短语纠错不能保证命中文档,通过collate指定查询语句来标识是否命中文档。
  • prune, 返回结果中标识是否命中

    <br /> GET top500_company_names/_search<br /> {<br /> "suggest": {<br /> "my_suggestion": {<br /> "text": "中国石头化工集团有限公司",<br /> "phrase": {<br /> "field": "name",<br /> "size": 3,<br /> "direct_generator": [<br /> {<br /> "field": "name",<br /> "size": 1,<br /> "max_edits": 1,<br /> "min_word_length": 2,<br /> "suggest_mode": "always"<br /> }<br /> ],<br /> "max_errors": 1,<br /> "highlight": {<br /> "pre_tag": "<em>",<br /> "post_tag": "</em>"<br /> },<br /> "collate": {<br /> "query": {<br /> "source": {<br /> "match": {<br /> "{{field_name}}": "{{suggestion}}"<br /> }<br /> }<br /> },<br /> "params": {<br /> "field_name": "name"<br /> },<br /> "prune": true<br /> }<br /> }<br /> }<br /> }<br /> }<br />

    1. 短语纠错 结果
  • collate_match, 标识是否命中文档

    <br /> {<br /> "my_suggestion" : [<br /> {<br /> "text" : "中国石头化工集团有限公司",<br /> "offset" : 0,<br /> "length" : 12,<br /> "options" : [<br /> {<br /> "text" : "中国 石油 化工 集团 有限公司",<br /> "highlighted" : "中国 <em>石油</em> 化工 集团 有限公司",<br /> "score" : 4.7643356E-5,<br /> "collate_match" : true<br /> }<br /> ]<br /> }<br /> ]<br /> }<br />

    小结

  • 在ES中,仅返回当搜索组不在词库中,且词库中存在与搜索词小于2个编辑距离的词作为候选。
  • 短语纠错词列表默认是不检查纠错后的短语能否命中文档的。
  • 在短语纠错中,collate 是必要的,否则无法保障纠错后的词能命中结果。