取消某个索引与别名的关联关系
tacsklet 回复了问题 • 3 人关注 • 2 个回复 • 2740 次浏览 • 2020-08-14 09:44
是否可以自己制造es的底层数据
Charele 回复了问题 • 2 人关注 • 1 个回复 • 1734 次浏览 • 2020-08-11 11:14
2. ES之从零开始 | 纠错(Did You Mean)
Ricky_Lau 发表了文章 • 1 个评论 • 5878 次浏览 • 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)算法来提供纠错功能。
- 模拟拼写错误,发送纠错请求
- 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 />
- 根据拼写错误的关键词,获取纠错词
- 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 />
- 中文不像英文单词那么长,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 />
- Demo 3的纠错请求结果
<br /> {<br /> "my_suggestion" : [<br /> {<br /> "text" : "太苹",<br /> "offset" : 0,<br /> "length" : 2,<br /> "options" : [ ]<br /> }<br /> ]<br /> }<br /> <br />
- 原来是两个参数限制了结果的返回
- 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 />
- 两个字纠错结果
<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 />
- 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 />
- 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 />
- 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 />
- 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 />
- 通过编辑距离控制纠错词列表
- 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 />
- 通过编辑距离控制纠错词列表结果
<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 />
- 纠错词的排序与返回个数
- 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 />
- 纠错词的排序与返回个数结果
<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 />
- 编辑距离与得分
- 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
- 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 />
- 通过纠错词最小文档阀值限制返回的个数
- 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 />
- 通过纠错词频率限制控制返回的个数
<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 />
- 第一个字错了,可以纠正么?
<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 />
- 第一个字错了,在上述语法中无法正常纠正
<br /> {<br /> "my_suggestion" : [<br /> {<br /> "text" : "大平洋",<br /> "offset" : 0,<br /> "length" : 3,<br /> "options" : [ ]<br /> }<br /> ]<br /> }<br />
- 第一个字错了的正确纠正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 />
- 第一个字错了的正确纠正结果
<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 />
- 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 />
- 公司名称纠错
<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 />
- 公司名称纠错结果
- 通常公司名称都是分词字段,使用默认 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)
多个词组合成一个整体进行拼写错误纠错。
- 短语纠错 查询
- 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 />
- 短语纠错 结果
- 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 是必要的,否则无法保障纠错后的词能命中结果。
index的时候那些routing信息存了有什么用???
zmc 回复了问题 • 4 人关注 • 3 个回复 • 1517 次浏览 • 2020-08-26 19:35
ServiceLoader 加载不到类
Charele 回复了问题 • 2 人关注 • 1 个回复 • 3486 次浏览 • 2020-08-09 14:04
请问一下 elasticsearch-rest-high-level-client 序列化的问题
回复brukfeng 回复了问题 • 0 人关注 • 1 个回复 • 2106 次浏览 • 2020-08-09 10:01
Filter过滤上下文的性能疑问
pony_maggie 回复了问题 • 3 人关注 • 2 个回复 • 2002 次浏览 • 2020-08-09 18:24
es从6.8升级到7.5之后,查询更慢了???
ScriptShi 回复了问题 • 3 人关注 • 2 个回复 • 1748 次浏览 • 2020-08-14 16:39
logstash消费kafka,日志顺序发生了改变
pony_maggie 回复了问题 • 2 人关注 • 1 个回复 • 1181 次浏览 • 2020-08-08 16:33
如果一个query查询出若干条数据, 但是我只想从第n条到第m条数据求和, 能用聚合分析吗?我该怎么操作?求大神指点
pony_maggie 回复了问题 • 2 人关注 • 1 个回复 • 1932 次浏览 • 2020-08-12 10:05
elasticsearch scripts如何查询_id(已解决)
回复chenkongzhang 发起了问题 • 1 人关注 • 0 个回复 • 2476 次浏览 • 2020-08-07 14:05
ES7.4 写数据时出现的问题,写了就崩 错误日志如下
Charele 回复了问题 • 3 人关注 • 4 个回复 • 4614 次浏览 • 2020-08-07 17:26