Match Query
匹配查询可以接受文本、数字及日期数据,进行分析然后构造查询。
GET /_search
{
"query": {
"match" : {
"message" : "this is a test"
}
}
}
注意:message是字段名称,你可以替换任何字段的名称。
match
查询会先对搜索词进行分词
,分词完毕后再逐个对分词结果进行匹配,因此相比于term
的精确搜索,match
是分词匹配搜索,match
搜索还有两个相似功能的变种,一个是match_phrase
,一个是multi_match
。
例如,当我们搜索 “中国杭州”,搜索词会先分词为“中国”和“杭州”,只要文档中包含“中国“和“杭州“任意一个词,都会被搜索到。同term查询一样,最终能否查到结果也取决于文档的内部存储结构结构,内部存储结构有分词和未分词2种情况,具体参见Term Query中 “term query 和 match query的不同之处”章节
match
match query
查询的类型为boolean, 这意味着将对提供的查询文本进行分析,并且分析过程将从提供的文本中构造一个boolean查询。运算符标志可以设置为or
或and
控制布尔子句(默认为or
)。 可以使用minimum_should_match
这个参数来设置要匹配的可选的should
子句的最小数量。
这是一个提供其他参数的示例(请注意结构略有变化,消息是字段名称):
GET /_search
{
"query": {
"match" : {
"message" : {
"query" : "this is a test",
"operator" : "and" //操作设置为and,表明分词后,每个词都要存在
}
}
}
}
可以将分析器设置为控制哪个分析器将对文本执行分析过程。 它默认为字段显式映射定义或默认的搜索分析器。
可以将lenient参数设置为true,以忽略由数据类型不匹配引起的异常,例如尝试使用文本查询字符串查询数字字段。 默认为false
。
operator参数例子
我们来看个operator的实际例子,仍然复用Term Query中 “term query 和 match query的不同之处”章节的索引结构和数据:
1.建索引和插入一条数据
PUT my_index //建一个索引
{
"mappings": {
"_doc": {
"properties": {
"full_text": {
"type": "text" //text类型,会分词
},
"exact_value": {
"type": "keyword" //keyword类型,不会分词
}
}
}
}
}
PUT my_index/_doc/1 //插入一条数据
{
"full_text": "Quick Foxes!",
"exact_value": "Quick Foxes!"
}
2.默认值or查询
我们针对full_text
字段进行查询,full_text
内部存储是分词的, 内部存储为[quick, foxes]
,2个单词,我们使用match
查询时,查询条件也会分词,分词结果为[quick, run]
,2个单词,那么operator
默认为 or
,即查询条件数组中的单词,只要有一个符合存储数组中的值,那么认为匹配,如果匹配的个数越多,则score越大,排序越靠前。
curl -XGET "10.40.164.63:9200/my_index/_search" --header "Content-Type:application/json" -d '
{
"query": {
"match": {
"full_text": "Quick run!" //查询条件分词后第二个词是run,而内部存储的是Foxes
}
}
}'
注意:查询条件分词后第二个词是run,而内部存储的是Foxes
扫描二维码关注公众号,回复: 11899265 查看本文章
上面的例子结果:
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1, //查询到了
"max_score": 0.2876821, //如果查询条件为“Quick Foxes”,得分翻倍为0.5753642
"hits": [{
"_index": "my_index",
"_type": "_doc",
"_id": "1",
"_score": 0.2876821,
"_source": {
"full_text": "Quick Foxes!",
"exact_value": "Quick Foxes!"
}
}]
}
}
2.and查询
即查询条件数组中的单词,全部符合存储数组中的值,那么认为匹配,只要有一个不符合,则不匹配。
curl -XGET "10.40.164.63:9200/my_index/_search" --header "Content-Type:application/json" -d '
{
"query": {
"match": {
"full_text": {
"query" : "Quick run!",
"operator" : "and" //and查询
}
}
}
}'
由于分词后的run不符合,因此查询结果为空。
fuzziness
模糊性允许基于要查询的字段类型进行模糊匹配。 有关允许的设置,请参见“模糊性”。
在这种情况下,可以设置prefix_length
和max_expansions
来控制模糊过程。 如果设置了模糊选项,则查询将使用top_terms_blended_freqs _ $ {max_expansions}作为其重写方法,Fuzzy_rewrite
参数允许控制如何重写查询。
默认情况下允许使用模糊转置(ab→ba),但可以通过将Fuzzy_transpositions
设置为false
来禁用模糊转置。
请注意,“模糊匹配”不适用于带有同义词的“词语”,因为在引擎盖下,这些术语被扩展为混合术语频率的特殊同义词查询,这不支持模糊扩展。
GET /_search
{
"query": {
"match" : {
"message" : {
"query" : "this is a testt",
"fuzziness": "AUTO"
}
}
}
}
模糊性
模糊匹配 对待 “模糊” 相似的两个词似乎是同一个词。首先,我们需要对我们所说的 模糊性 进行定义。
在1965年,Vladimir Levenshtein 开发出了 Levenshtein distance, 用来度量从一个单词转换到另一个单词需要多少次单字符编辑。他提出了三种类型的单字符编辑:
- 一个字符 替换 另一个字符: _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
- 把 e 和 a 进行换位:b_ae_ver → b_ea_ver
这三个步骤表示 Damerau-Levenshtein edit distance 编辑距离为 3 。
显然,从 beaver 转换成 bieber 是一个很长的过程—他们相距甚远而不能视为一个简单的拼写错误。 Damerau 发现 80% 的拼写错误编辑距离为 1 。换句话说, 80% 的拼写错误可以对原始字符串用 单次编辑 进行修正。
Elasticsearch 指定了 fuzziness 参数支持对最大编辑距离的配置,默认为 2 。
当然,单次编辑对字符串的影响取决于字符串的长度。对单词 hat 两次编辑能够产生 mad , 所以对一个只有 3 个字符长度的字符串允许两次编辑显然太多了。 fuzziness
参数可以被设置为 AUTO
,这将导致以下的最大编辑距离:
- 字符串只有 1 到 2 个字符时是 0
- 字符串有 3 、 4 或者 5 个字符时是 1
- 字符串大于 5 个字符时是 2
当然,你可能会发现编辑距离 2 仍然是太多了,返回的结果似乎并不相关。 把最大 fuzziness
设置为 1 ,你可以得到更好的结果和更好的性能。
zero_terms_query
暂不翻译
Cutoff frequency
暂不翻译