ElasticSearch-query-match_匹配查询
2025-01-22 08:19:30    1.4k 字   
This post is also available in English and alternative languages.

ElasticSearch版本:6.5.0(点击跳转官方文档)

全文查询


match查询会对查询 语句 / 词 进行分词,分词后查询语句中任何一个词项被匹配,文档就会被检索到。

假设现在查询语句:“高等专业教材”,分词结果:“高等”、“专业”、“教材” 这三个词项。

match query 属于 boolean 查询类型,在分析过程中会从提供的文本中构造一个boolean查询。


1. match 和 term 的区别

match查询时,es根据给定字段,提供合适的分析器进行分词,分词后查询语句中任何一个词项被匹配,文档就会被检索到;

term查询不会有分析器分析的过程。


2. match 查询

1
2
3
4
5
6
7
8
9
10
11
GET /bookdatas/bookType/_search
{
"query": {
"match": {
"name": {
"query": "高等专业教材"
}
}
},
"_source": "name"
}

Elasticsearch 执行上面这个 match 查询的步骤是:

1.检查字段类型 2.分析查询字符串 3.查找匹配文档 4.为每个文档评分

上面这个例子:“高等专业教材”,分词结果:“高等”、“专业”、“教材” 这三个词项。

它在内部实际上先执行三次 term 查询,然后将三次查询的结果合并作为最终结果输出。

任何文档只要 name 字段里包含 指定词项中的至少一个词 就能匹配,被匹配的词项越多,文档就越相关。

match-搜索分析器

3. operator

operator 参数,匹配关键词的逻辑符号,可以用来提高查询精度

使用match查询可以发现,默认情况下,多个词之间的关系是 or ,如果想提高查询结果精度,可以使用and来找到所有匹配的文档。

查询name字段中既包含 ‘机械’ 又包含(and) ‘制图’ 的结果

1
2
3
4
5
6
7
8
9
10
11
12
GET /bookdatas/bookType/_search
{
"query": {
"match": {
"name": {
"query": "高等专业教材",
"operator": "and"
}
}
},
"_source": "name"
}

在分析器中可以看到,booleanQuery后面的词项都增加了加号。

文档name字段,必须包含这三个词项,才能被检索出来。

match-operator-搜索分析器

4. analyzer

analyzer 可以指定文本分析过程中,使用哪个分析器对文本进行分析。

如果没有指定分词器,默认使用字段显式映射(mapping)中的定义

这里使用IK分词器,IK分词器有两种模式:

模式说明
ik_max_word文本做最细粒度拆分
ik_smart文本做粗粒度拆分

4.1. i k_smart

粗粒度分词

1
2
3
4
5
6
7
8
9
10
11
12
13
GET /bookdatas/bookType/_search
{
"query": {
"match": {
"name": {
"query": "高等专业国家系列教材",
"operator": "and",
"analyzer": "ik_smart"
}
}
},
"_source": "name"
}

分析器中显示,使用 ik_smart 分词器,"高等专业国家系列教材"被分词为:“高等”、“专业”、“国家”、“系列”、“教材”

match-analyzer-1-搜索分析器

4.2. ik_max_word

细粒度分词

1
2
3
4
5
6
7
8
9
10
11
12
13
GET /bookdatas/bookType/_search
{
"query": {
"match": {
"name": {
"query": "高等专业国家系列教材",
"operator": "and",
"analyzer":"ik_max_word"
}
}
},
"_source": "name"
}

分析器中显示,使用 ik_smart 分词器,"高等专业国家系列教材"被分词为:“高等”、“国家”、“系列”、“专业”、“家系”、“教材”

match-analyzer-2-搜索分析器

5. lenient

lenient参数设置为true,可以忽略数据类型不匹配抛出的异常;默认值为false、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
GET /bookdatas/bookType/_search
{
"size": 50,
"query": {
"match": {
"name": {
"query": "高等专业国家系列教材",
"operator": "and",
"analyzer": "ik_smart",
"lenient": "false"
}
}
}
}

6. fuzziness

通过设置 fuzziness 参数,可以控制查询时模糊匹配程度。

碍于文章篇幅,这里不深究,后面专门开一篇学习下。

fuzziness 参数可以设置为:

  • AUTO 自动模式;基于词语长度自动选择编辑距离。也可以设置字符距离规则范围 AUTO:[low],[high],不指定参数low和high,默认为3,6,即 AUTO:3,6
  • 0,1,2 可以设置成具体的编辑距离,最大为2。
  • 0…2 对于长度小于2的字符串,必须绝对匹配。
  • 3…5 对于长度范围在3到5的字符串,允许一个编辑距离。
  • >5 对于长度大于5的字符串,允许两个编辑距离。

AUTO模式能够自动根据字符串长度进行选择,建议优先使用AUTO模式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
GET /bookdatas/bookType/_search
{
"query": {
"match": {
"name": {
"query": "高等专业国家系列教材",
"operator": "and",
"analyzer": "ik_smart",
"fuzziness": "AUTO"
}
}
},
"_source": "name"
}

7. zero_terms_query

分析器移除所有分词后,是否返回文档。

如 当查询内容中都是停用词时,所有的分词分析器停用词过滤器过滤掉时,是否返回文档。

默认为none:不返回任何文档。all:返回所有文档


8. cutoff_frequency

挖个坑,日后再填


9. auto_generate_synonyms_phrase_query

是否开启同义词匹配,默认为false。


10. Java Client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@Override
public SearchResponse search(String field, String text, int size, Operator operator, String analyzer) {
SearchRequest searchRequest = RequestUtils.createSearchRequest(indices);
searchRequest.types(typeName);

SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.size(size);
sourceBuilder.timeout(TimeValue.timeValueMillis(300L));

MatchQueryBuilder matchQuery = QueryBuilders.matchQuery(field, text);

if (StringUtils.isNotBlank(analyzer)) {
matchQuery.analyzer(analyzer);
}

if (Objects.nonNull(operator)) {
matchQuery.operator(operator);
}

SearchSourceBuilder builder = sourceBuilder.query(matchQuery);
searchRequest.source(builder);

return search(searchRequest);
}

private SearchResponse search(SearchRequest request) {
return restHighClient.execute(highClient -> highClient.search(request, RequestOptions.DEFAULT));
}

11. Reference