0%

ElasticSearch的几种查询模式

摘要:实现 ES 结果最大匹配数修改、筛选并嵌套聚类,比较多种模式检索的差异。

结果最大匹配数修改

官方文档说明

默认情况下,elasticsearch 搜索请求将准确地计算总点击数,最多 10,000 个文档。如果与查询匹配的总点击数大于此值,则响应将指示返回的值是一个下限,例如"gte"

不修改track_total_hits的结果:

1
2
3
4
5
6
7
8
9
10
GET /kibana_sample_data_logs/_search
--------

"hits" : {
"total" : {
"value" : 10000,
"relation" : "gte"
}
}

修改track_total_hits后的结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
GET /kibana_sample_data_logs/_search
{
"track_total_hits": true
}
--------

"hits" : {
"total" : {
"value" : 14074,
"relation" : "eq"
}}


此外设置index.max_result_window上限:

1
2
3
4
PUT _all/_settings
{
"index.max_result_window":"200000"
}

筛选并嵌套聚类

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
29
30
GET /kibana_sample_data_flights/_search?size=0
{
"query": {
"bool": {
"must": [
{
"query_string": {
"default_field": "DestCountry",
"query": "AU OR CN OR US"
}
}
]
}
},"aggs": {
"按照国家聚类": {
"terms": {
"field": "DestCountry",
"size": 10
},"aggs": {
"按照城市聚类": {
"terms": {
"field": "DestCityName",
"size": 100
}
}
}
}
}
}

查询结果(部分):

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
29
30
{
"key": "CN",
"doc_count": 1096,
"按照城市聚类": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "Xi'an",
"doc_count": 526
},
{
"key": "Shanghai",
"doc_count": 479
},
{
"key": "Guangzhou",
"doc_count": 48
},
{
"key": "Chengdu",
"doc_count": 29
},
{
"key": "Beijing",
"doc_count": 14
}
]
}
}

几种检索模式的特性

检索全部文档

1
GET /kibana_sample_data_ecommerce/_search?size=100&_source=category

查询结果(总数):

1
2
3
4
"total" : {
"value" : 4675,
"relation" : "eq"
}

match

  • 模糊匹配,需要指定字段名,但是输入会进行分词,比如”hello world”会进行拆分为 hello 和 world,然后匹配,如果字段中包含 hello 或者 world,或者都包含的结果都会被查询出来,也就是说 match 是一个部分匹配的模糊查询。查询条件相对来说比较宽松。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
GET /kibana_sample_data_ecommerce/_search?size=4000&_source=category
{
"query": {
"bool": {
"must": [
{
"match": {
"category": "Men's Clothing"
}
}
]
}
}
}

查询结果(多于实际数量):

1
2
3
4
"total" : {
"value" : 4213,
"relation" : "eq"
}

term

  • 这种查询和 match 在有些时候是等价的,比如我们查询单个的词 hello,那么会和 match 查询结果一样,但是如果查询”hello world”,结果就相差很大,因为这个输入不会进行分词,就是说查询的时候,是查询字段分词结果中是否有”hello world”的字样,而不是查询字段中包含”hello world”的字样,elasticsearch 会对字段内容进行分词,”hello world”会被分成 hello 和 world,不存在”hello world”,因此这里的查询结果会为空。这也是 term 查询和 match 的区别
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
GET /kibana_sample_data_ecommerce/_search?size=100&_source=category
{
"query": {
"bool": {
"must": [
{
"term": {
"category": {
"value": "Men's Clothing"
}
}
}
]
}
}
}

查询结果(查不到):

1
2
3
4
"total" : {
"value" : 0,
"relation" : "eq"
}

match_phrase

  • 会对输入做分词,但是需要结果中也包含所有的分词,而且顺序要求一样。以”hello world”为例,要求结果中必须包含 hello 和 world,而且还要求他们是连着的,顺序也是固定的,hello that word 不满足,world hello 也不满足条件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
GET /kibana_sample_data_ecommerce/_search?size=4000&_source=category
{
"query": {
"bool": {
"must": [
{
"match_phrase": {
"category": "Men's Clothing"
}
}
]
}
}
}

查询结果(等于实际数量):

1
2
3
4
"total" : {
"value" : 2024,
"relation" : "eq"
}

query_string

  • 和 match 类似,但是 match 需要指定字段名,query_string 是在所有字段中搜索,范围更广泛。

对检索的关键词不加双引号

  • 属于部分匹配的模糊查询
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
GET /kibana_sample_data_ecommerce/_search?size=4000&_source=category
{
"query": {
"bool": {
"must": [
{
"query_string": {
"default_field": "category",
"query": "Men's Clothing"
}
}
]
}
}
}

查询结果(多于实际数量):

1
2
3
4
5
"total" : {
"value" : 4213,
"relation" : "eq"
}

对检索的结果加上转义后的双引号

  • 精确匹配该词汇
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
GET /kibana_sample_data_ecommerce/_search?size=4000&_source=category
{
"query": {
"bool": {
"must": [
{
"query_string": {
"default_field": "category",
"query": "\"Men's Clothing\""
}
}
]
}
}
}

查询结果(等于实际数量):

1
2
3
4
"total" : {
"value" : 2024,
"relation" : "eq"
}