1.概述

转载:https://www.cnblogs.com/richaaaard/p/5282630.html

摘要

我们喜欢在对结构化数据(如:日期和价格)做查询时,结果只返回那些能精确匹配的文档。但是,好的全文搜索不应该有这样的限制。相反,我们可以扩大范围,包括更多可能匹配的词语,使用相关度评分将更匹配的文档放置在结果集的顶部。

事实上,只做精确匹配的全文搜索很有可能会让用户失望,难道我们不希望搜索 “quick brown fox” 可以匹配到包含 “fast brown foxes” 的文档,“Johnny Walker” 可以匹配 “Johnnie Walker”“Arnold Shcwarzenneger” 可以匹配 “Arnold Schwarzenegger”

如果文档确实精确包含用户的搜索条件,那么它们应该出现在结果集的顶部,而弱匹配可以置于结果列表的稍后地方。如果没有精确的匹配,至少我们可以为用户提供潜在匹配的可能,它们甚至可能是用户搜索的初衷!

我们已经在 规则化标记(Normalizing Tokens) 介绍了处理变音词的匹配方式,在 缩减单词至词根形式(Reducing Words to Their Root Form) 中介绍了词语的词干提取方式,在 同义词(Synonyms) 中介绍了同义词的处理方式,但是所有这些方法都以单词是正确拼写这个条件为前提,或者说每个词的拼写方式只有一种

模糊匹配允许在查询时匹配拼写错误的词,语音标记过滤器可以在索引时用来语音匹配。

2.版本

elasticsearch版本: elasticsearch-2.x

3.内容

3.1 模糊逻辑(Fuzziness)

模糊匹配将两个模糊相似的词作为同一词语处理,首先,我们须要定义什么是模糊性。

在 1965 年,Vladimir Levenshtein 开发了 Levenshtein 距离算法,它可以计算从一个单词变成另外一个单词时,单个字符改变的总次数。它提出了三种类型的单字符修改方式:

  • 将一个字符替换成为另外一个:f ox → b ox
  • 插入新的字符:sic → sic k
  • 删除字符:b l ack → back

Frederick Damerau 后来对这些操作进行了扩展,新增了一种方式:

  • 交换两个相邻字符的位置:st ar → ts ar

例如,将单词 bieber 转换成 beaver 需要以下步骤:

  • 将 b 替换成 v : bie b er → bie v er
  • 将 i 替换成 a : b i ever → b a ever
  • 交换 a 和 e 的位置: b ae ver → b ea ver

这三步用 Damerau-Levenshtein 法表示的距离是 3 。

显然,bieber 与 beaver 有很长一段距离,它们相距太远而不能被认为是简单的拼写错误。Damerau 观察到 80% 的人为拼写错误的距离是 1 。换句话说,有 80% 的拼写错误可以通过单次字符修改得到原始的字符串。

Elasticsearch 支持一个最大的编辑距离是 2 ,可以通过参数 fuzziness 来指定。

当然,单次修改的影响还取决于被修改字符串的长度。单词 hat 经两次修改可以变成 mad ,所以允许长度为 3 的字符串修改两次有点过度。参数 fuzziness 可以被设置成 AUTO ,代表以下三中最大编辑距离:

  • 0 对于长度为 1 或 2 的字符串
  • 1 对于长度为 3、4 或 5 的字符串
  • 2 对于长度大于 5 的字符串

当然,可能会发现 2 步修改仍然过度,返回的结果看上去并不相关。当最大 fuzziness 值为 1 时,我们可能会得到更好的搜索结果和更好的性能。

3.2 模糊查询(Fuzzy Query)

fuzzy 查询和使用 term 查询的 fuzzy 特性是等价的。通常我们很少会自己直接使用它,但是理解它的工作方式有助于我们在高层 match 查询中利用模糊的特性。

为了理解它是如何工作的,我们先新建索引一些文档:

POST /my_index-0002/my_type/_bulk
{ "index": { "_id": 1 }}
{ "text": "Surprise me!"}
{ "index": { "_id": 2 }}
{ "text": "That was surprising."}
{ "index": { "_id": 3 }}
{ "text": "I wasn't surprised."}

现在我们就可以运行 fuzzy 查询搜索 surprize:

GET /my_index-0002/my_type/_search
{"query": {"fuzzy": {"text": "surprize"}}
}

查询结果如下

    {"_index" : "my_index-0002","_type" : "my_type","_id" : "1","_score" : 0.9559981,"_source" : {"text" : "Surprise me!"}},{"_index" : "my_index-0002","_type" : "my_type","_id" : "3","_score" : 0.69983494,"_source" : {"text" : "I wasn't surprised."}}

fuzzy 查询是一个词项级别的查询,所以它没有做任何分析的工作。它接收单个词项,并且根据指定的模糊逻辑在字典中查找匹配的所有词项。默认的 fuzziness 值是 AUTO

在我们的例子中,surprize 距离 2 以内的词有 surprise 和 surprised,所以文档 1 和 3 是匹配的。我们可以通过以下查询将匹配结果缩小至 surprise :

GET /my_index-0002/my_type/_search
{"query": {"fuzzy": {"text": {"value": "surprize","fuzziness": 1}}}
}

结果如下

    {"_index" : "my_index-0002","_type" : "my_type","_id" : "1","_score" : 0.9559981,"_source" : {"text" : "Surprise me!"}}

3.3 提升性能(Improving Performance)

fuzzy 查询接受原始词项并为其构建一个 Levenshtein 自动机(automaton) ,这个结构有如一个图,它能表示与原始字符串相距指定编辑距离值以内的所有可能字符串

模糊查询随后使用这个自动机逐步高效的在字典中匹配所有词项,一旦收集到字典里所有的匹配词项,它便能计算出所有与之匹配的文档

当然,由于索引里存储的数据类型不同,一个编辑距离为 2 可以与大量词匹配,性能也会非常差。以下两个参数可以用来限制对性能的不良影响:

prefix_length

设置字符串不会被“模糊化”的起始长度。多数拼写错误出现在词语的末尾处,而不是开始处。比如,当 prefix_length 的值为 3 时,我们可以大大减少需要匹配词项的数目。

max_expansions

如果模糊查询扩展到三或四个选项的时候,这些新选项可能还是有意义的,但当它生成 1,000 个选项时,它们实际上毫无意义。用 max_expansions 来限制生成选项的总数,模糊查询会搜集匹配的词项,直到找不出更多匹配或词项数目达到 max_expansions 数值的限制。

3.4 模糊匹配查询(Fuzzy match Query)

match 查询自带支持模糊匹配的功能:

GET /my_index-0002/my_type/_search
{"query": {"match": {"text": {"query": "SURPRIZE ME!","fuzziness": "AUTO","operator": "and"}}}
}

查询结果如下

  "hits" : {"total" : {"value" : 1,"relation" : "eq"},"max_score" : 2.0485673,"hits" : [{"_index" : "my_index-0002","_type" : "my_type","_id" : "1","_score" : 2.0485673,"_source" : {"text" : "Surprise me!"}}]}

查询字符串首先经过分析,然后生成词项 [surprize, me],最后每个词项用指定的 fuzziness(模糊逻辑) 进行模糊化处理。

类似地,multi_match 查询也支持模糊逻辑,但它只支持两种类型 best_fields 或 most_fields

GET /my_index-0002/my_type/_search
{"query": {"multi_match": {"fields": ["text","title"],"query": "SURPRIZE ME!","fuzziness": "AUTO"}}
}

查询结果

    "hits" : [{"_index" : "my_index-0002","_type" : "my_type","_id" : "1","_score" : 2.0485673,"_source" : {"text" : "Surprise me!"}},{"_index" : "my_index-0002","_type" : "my_type","_id" : "3","_score" : 0.69983494,"_source" : {"text" : "I wasn't surprised."}}]

match 和 multi_match 查询都能支持 prefix_length 和 max_expansions 参数。

小贴士

模糊逻辑只能使用于两种基本查询 match 和 multi_match,而无法使用于短语匹配,常用词项或跨字段匹配。

模糊度的评分(Scoring Fuzziness)

用户喜欢模糊查询,他们以为这些查询总会奇妙的找到正确的拼写结果。不幸的是,事实却无法激动人心。

假设我们有 1,000 个文档包含词语 “Schwarzenegger”,其中只有 1 个文档里有错误拼写 “Schwarzeneger”,根据 TF/IDF 的理论,这个错误拼写比正确拼写更具相关性,因为它在文档里出现的次数要少得多

换句话说,如果我们同等对待模糊匹配和其他匹配,那么我们就会更偏向错误拼写而不是正确拼写,这会使用户感到抓狂的。

小贴士

模糊匹配不应用于以评分为目的的查询,而只能当有错误拼写时,用于扩大匹配词项的匹配范围。

默认情况下,match 查询给所有模糊匹配的分数总是 1 。这足以使潜在的匹配出现在结果的末尾,而不用影响到非模糊查询的相关度评分计算。

小贴士

模糊查询本身并没有刚开始看起来那么有用,它们最好作为高级功能的一部分,例如 输入即搜索 completion 完成建议器 或 你想查找 词组建议器。

3.5 语音匹配(Phonetic Matching)

最后,令人绝望的是,试图匹配那些听上去相似的词,这些词的拼写甚至是不同的。

现存一些算法可以将词语转换成语音形式表示Soundex 算法是它们的始祖,其他所有类似算法都是 Soundex 的改进或定制形式,例如 MetaphoneDouble Metaphone (它对语音匹配扩展到其他语言而不只是英语),Caverphone 算法可以匹配新西兰姓名,Beider-Morse 算法以 Soundex 算法为基础,但它能更好的匹配德语和依地语姓名,Kölner Phonetik 对德语词支持更好。

我们从上面一串算法中要学到的是语音算法都相当粗糙,太依赖于它们针对设计的语言,这些语言可以是英语,也可以是德语,这限制了它们的可用性。不过,如果与其他技术相结合,为了处理某种问题,语音匹配也可以是个有用的工具。

首先,我们需要从下面网址安装语音分析插件 https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-phonetic.html ,为集群每个节点都安装,然后重启每个节点。

安装后,我们可以创建一个自定义分析器,尝试使用其中一个语音标记过滤器:

PUT /my_index
{"settings": {"analysis": {"filter": {"dbl_metaphone": { #1"type":    "phonetic","encoder": "double_metaphone"}},"analyzer": {"dbl_metaphone": {"tokenizer": "standard","filter":    "dbl_metaphone" #2}}}}
}

1 首先,配置自定义 phonetic 语音标记过滤器以及 double_metaphone 编码器。

2 然后在自定义分析器中使用自定义的标记过滤器。

现在使用 analyze API 对其测试:

GET /my_index/_analyze?analyzer=dbl_metaphone
Smith Smythe

Smith 和 Smythe 在同一位置各生成两个标记:SM0 和 XMT。分析 John、Jon 和 Johnnie 会都生成两个标记 JN 和 AN,但 Jonathon 会生成标记 JN0N 和 ANTN。

语音分析器和其他分析器的使用方式类似,首先为字段设置映射,然后在对数据建立索引:

PUT /my_index/_mapping/my_type
{"properties": {"name": {"type": "string","fields": {"phonetic": { #1"type":     "string","analyzer": "dbl_metaphone"}}}}
}PUT /my_index/my_type/1
{"name": "John Smith"
}PUT /my_index/my_type/2
{"name": "Jonnie Smythe"
}

1 name.phonetic 字段使用自定义的 dbl_metaphone 分析器。

用 match 查询来搜索:

GET /my_index/my_type/_search
{"query": {"match": {"name.phonetic": {"query": "Jahnnie Smeeth","operator": "and"}}}
}

这个查询同时返回两个文档,这样表明语音查询是有多粗糙。使用语音算法进行评分通常也没有多大意义。使用语音算法的目的不在于提高精度,而在于提高召回,扩大撒网范围从而获得任何可能匹配的文档。

通常将语音算法的结果作为其他算法或计算机的输入信息,要比直接将结果给人使用要靠谱得多。

【Elasticsearch】语言处理系列之打字或拼写错误 模糊匹配 字段纠错 Fuzzy multi_match相关推荐

  1. ElasticSearch 2 (26) - 语言处理系列之打字或拼写错误

    ElasticSearch 2 (26) - 语言处理系列之打字或拼写错误 摘要 我们喜欢在对结构化数据(如:日期和价格)做查询时,结果只返回那些能精确匹配的文档.但是,好的全文搜索不应该有这样的限制 ...

  2. ElasticSearch 2 (21) - 语言处理系列之单词识别

    ElasticSearch 2 (21) - 语言处理系列之单词识别 摘要 一个英语单词相对容易识别:因为英语单词是被空格或(某些)标点符号隔开的.但在英语中也有反例:you're 这个词是一个单词还 ...

  3. ElasticSearch 2 (20) - 语言处理系列之如何开始

    ElasticSearch 2 (20) - 语言处理系列之如何开始 摘要 Elasticsearch 配备了一组语言分析器,为世界上大多数常见的语言提供良好的现成基础支持. 阿拉伯语.亚美尼亚语,巴 ...

  4. ElasticSearch 2 (25) - 语言处理系列之同义词

    ElasticSearch 2 (25) - 语言处理系列之同义词 摘要 词干提取有助于通过简化屈折词到它们词根的形式来扩展搜索的范围,而同义词是通过关联概念和想法来扩展搜索范围的.或许没有文档能与查 ...

  5. 分段函数if语句_C语言函数系列之库函数中基础必会函数(一)

    !!!阅前提醒:!!! 此文为c语言函数系列的第一篇,全系列字数将达到1w字以上且全为干货内容,请各位仔细阅读并打开编译器运行文章中出现的代码进行试验以确保能理解文章内容 if判断函数(以图中显示代码 ...

  6. 剖析Elasticsearch集群系列之二:分布式的三个C、translog和Lucene段

    2019独角兽企业重金招聘Python工程师标准>>> 剖析Elasticsearch集群系列之二:分布式的三个C.translog和Lucene段 博客分类: java 搜索引擎, ...

  7. Go语言自学系列 | golang标准库bufio

    视频来源:B站<golang入门到项目实战 [2021最新Go语言教程,没有废话,纯干货!持续更新中...]> 一边学习一边整理老师的课程内容及试验笔记,并与大家分享,侵权即删,谢谢支持! ...

  8. C语言入门系列 -运算符

    C语言入门系列 - 运算符 第一节 C 语言基础以及基本数据类型 第二节 C 语言运算符 第三节 C 语言控制语句 第四节 C 语言自定义函数 第五节 C 语言修饰变量的关键字 第六节 C 语言构造数 ...

  9. C语言入门系列 - 自定义函数

    C语言入门系列 - 自定义函数 第一节 C 语言基础以及基本数据类型 第二节 C 语言运算符 第三节 C 语言控制语句 第四节 C 语言自定义函数 第五节 C 语言修饰变量的关键字 第六节 C 语言构 ...

最新文章

  1. Sentinel 高可用流量管理框架
  2. Windows客户端C/C++编程规范“建议”——变量和常量
  3. 上传照片表单提交包括文本框下拉条等,如何取文本框的值
  4. 看动画学算法之:平衡二叉搜索树AVL Tree
  5. python随机生成10个整数列表_python_随机产生10个整数后找出最小值,最大值。
  6. C++ 构造函数与析构函数
  7. Number类型及方法(js)
  8. 小程序 微信统计表格_微信小程序登录机制
  9. 逻辑分析题汇总(一)
  10. 微生物组-扩增子16S分析和可视化(2022.10)
  11. 【推荐算法论文】矩阵分解算法
  12. 跟益达学Solr5之使用Ansj分词器
  13. 爬虫代理哪家强?十大付费代理详细对比评测!
  14. git 取消托管文件
  15. 浙江海盐已经试行“核供暖”,南方到底该不该供暖?南方人顶起~
  16. 如何在 FlowUs、Notion 等笔记软件中进行时间管理?
  17. c#:使用网易邮箱账号发送电子邮件
  18. PLC控制系统的软件设计
  19. HDU 1218 - Blurred Vision
  20. 《Kinect应用开发实战:用最自然的方式与机器对话》一3.1 Kinect for Xbox 360的产品设计...

热门文章

  1. 叮咚买菜更新招股书:发行价区间为23.5-25.5美元
  2. 《王者荣耀》宣布将推独立女子电竞赛事:跟进奥运会
  3. 2月份全球制造业PMI为55.6% 已连续8个月保持在50%以上
  4. 华为技术有限公司申请“荣耀视频”、“荣耀钱包”等商标
  5. 国内第四大运营商中国广电成立:5G 192号段要来了!
  6. 12499元!“不知名”折叠手机2分钟售罄,网友:备货就10台...
  7. 一把误操作卖出500万股,TCL科技李东生致歉:收益归公司
  8. Galaxy Note 20新爆料:至少有两款机型,处理器高低配
  9. 外媒:美国政府官员建议阻止英飞凌收购赛普拉斯
  10. 王一博、张艺兴等多位明星起诉医美平台更美App