Elasticsearch Query DSL 整理总结(二)—— 要搞懂 Match Query,看这篇就够了

引言

昨天是感恩节,上幼儿园的女儿在老师的叮嘱下,晚上为我和老婆洗了脚(形式上的^_^),还给我们每人端了一杯水。看着孩子一天天的长大,懂事,感觉很开心,话说咱们程序员这么辛苦是为了什么?不就是为了老婆,孩子,热炕头,有一个温暖幸福的家庭,再捎带着用代码改变一下世界吗?想到这里,顿时觉得学习,创作博客的劲头也的更足了。哈哈,扯远了,书归正传,今天我们来聊聊 Match Query。

Match Query 是最常用的 Full Text Query 。无论需要查询什么字段, match 查询都应该会是首选的查询方式。它既能处理全文字段,又能处理精确字段。

构建示例

为了能够在后面能深入理解 Match Query 中的各个属性的意义,我们先构建一个 index 示例(有兴趣的同学只要将下面字段粘贴到 sense 中就可以创建)。

PUT matchtest { } PUT matchtest/_mapping/people { "properties": { "age": { "type": "integer" }, "hobbies": { "type": "text" }, "name": { "type": "keyword" } } } PUT matchtest/people/1 { "name" : "Jim", "age": 10, "hobbies": "football, basketball, pingpang" } PUT matchtest/people/2 { "name" : "Tom", "age": 12, "hobbies": "swimming, football" } match operator 参数

match 查询是一种 bool 类型的查询。什么意思呢?举个例子,查询 people type 的 hobbies 为 football basketball

GET matchtest/people/_search { "query": { "match": { "hobbies": "football basketball" } } }

会将上面的两个文档都搜索出来。为什么?上面的查询其实隐藏了一个默认参数operator , 它的默认值是 or ,也就是说上面的查询也可以写成这种形式

GET matchtest/people/_search { "query": { "match": { "hobbies": { "query": "football basketball", "operator": "or" } } } }

这样就比较容易理解了,既然是 or 操作符,就表示只要查询的文档的 hobbies 字段中含有 football 和 basketball 任意一个,就可以被匹配到。

如果将 operator 操作符的值改为 and ,则表示需要同时包含 football 和 basketball , 得到的结果就只能是 文档 1 Jim 小朋友了。

analyzer

analyzer 属性是指在对查询文本分析时的分析器

如果没有指定则会使用字段mapping 时指定的分析器

如果字段在 mapping 时也没有明显指定,则会使用默认的 search analyzer。

这里我们也没有指定,就会使用默认的,就不举例了,在后面文章讲解 analyzer 时再拓展。

lenient 参数

默认值是 false , 表示用来在查询时如果数据类型不匹配且无法转换时会报错。如果设置成 true 会忽略错误。

例如, 例子中的 age 是 integer 类型的,如果查询 age=xxy ,就会导致无法转换而报错。

GET matchtest/_search { "query": { "match": { "age" : { "query": "xxx" } } } }

而如果将 lenient 参数设置为 true ,就会忽略这个错误

GET matchtest/_search { "query": { "match": { "age" : { "query": "xxx", "lenient": true } } } }

注意,如果将 age 字段的值设置为字符串 "10", 来查询,由于能够转换成整数,这时 elastic 内部会将 字符串先转换成整数再做查询,不会报错。

Fuzziness fuzzniess 参数

fuzziness 参数可以是查询的字段具有模糊搜索的特性。来先了解下什么是模糊搜索。

什么是模糊搜索?

模糊搜索是指系统允许被搜索信息和搜索提问之间存在一定的差异,这种差异就是“模糊”在搜索中的含义。例如,查找名字Smith时,就会找出与之相似的Smithe, Smythe, Smyth, Smitt等。

——百度百科

通过模糊搜索可以查询出存在一定相似度的单词,那么怎么计算两个单词是否有相似度以及相似度的大小呢?这就要了解下另外一个概念:Levenshtein Edit Distance

Levenshtein Edit Distance

Levenshtein Edit Distance 叫做莱文斯坦距离**,是编辑距离的一种。指两个字串之间,由一个转成另一个所需的最少编辑操作次数。允许的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。

例如,单词 "god" 只需要插入一个 'o' 字符就可以变为 "good",因此它们之间的编辑距离为 1。

fuzziness 参数取值规则

了解了上面两个概念,回过头再来看下 fuzziness 参数。

在查询 text 或者 keyword 类型的字段时, fuzziness 可以看做是莱文斯坦距离。

fuzziness 参数的取值如下

0,1,2 表示最大可允许的莱文斯坦距离

AUTO

会根据词项的长度来产生可编辑距离,它还有两个可选参数,形式为AUTO:[low],[high], 分别表示短距离参数和长距离参数;如果没有指定,默认值是 AUTO:3,6 表示的意义如下

0..2

单词长度为 0 到 2 之间时必须要精确匹配,这其实很好理解,单词长度太短是没有相似度可言的,例如 'a' 和 'b'。

3..5

单词长度 3 到 5 个字母时,最大编辑距离为 1

>5

单词长度大于 5 个字母时,最大编辑距离为 2

最佳实践: fuzziness 在绝大多数场合都应该设置成 AUTO

如果不设置 fuziness 参数,查询是精确匹配的。

来看例子,上面创建了一个 doc

PUT matchtest/people/1 { "name" : "Jim", "age": 10, "hobbies": "football, basketball, pingpang" }

设置 fuzziness 为 AUTO ,

其中 hobbies 字段的值 football 长度 > 5, 此时我们找一个编辑距离为 2 的单词 footba22 来查询,应该匹配到

其中 name 字段的值 jim 长度在 3 和 5 之间,此时找一个编辑距离为 1 的单词 jiO 应匹配到,而编辑距离为 2 的 jOO 就不应匹配到。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpwwfy.html