Elasticsearch查询

Elasticsearch查询详解

文档所需数据,请看 Elasticsearch index及数据的基础操作

一、引言

Elasticsearch是一个基于Lucene的搜索和分析引擎,它提供了一个分布式、多租户能力的全文搜索引擎,同时也是一个分布式实时分析搜索引擎。Elasticsearch以其强大的搜索和分析能力,广泛应用于日志分析、安全智能、业务搜索等场景。

二、Elasticsearch查询基础

Elasticsearch提供了一套丰富且灵活的查询语言,称为Query DSL(领域特定语言)。使用Query DSL,您可以执行各种结构化、非结构化、地理、面向度量的查询等。通过查询DSL,用户可以构建各种复杂查询,满足不同的搜索需求。

三、基础查询

  1. id查询

    通过文档ID查询文档是最直接且高效的方式。使用Elasticsearch的HTTP API,发送一个GET请求到特定的索引和文档ID即可获取文档。使用id查询可以立马查询出更新后的数据,条件查询需要自动刷新后才能被搜索到,或者手动Refresh

    1
    GET /your_index_name/_doc/your_document_id

    这个请求会返回指定索引(your_index_name)中指定ID(your_document_id)的文档。

    1
    GET index_test/_doc/id_1
  2. Match查询

    这是最基本的查询类型,用于执行全文搜索。它会将查询字符串分析成多个词条,并在索引中查找包含这些词条的文档。
    最常见的为match_all,将查询所有数据,当前没有设置size,所以只会返回10条。

    1
    2
    3
    4
    5
    6
    GET index_test/_search
    {
    "query": {
    "match_all": {}
    }
    }

    通过具体字段查询使用match,查询intro为打工人的数据,将查询出两条数据

    1
    2
    3
    4
    5
    6
    7
    8
    GET index_test/_search
    {
    "query": {
    "match": {
    "intro": "打工人"
    }
    }
    }
  3. Match_phrase查询

    与Match查询类似,但Match_phrase查询要求查询的词条在文档中以相同的顺序出现。
    使用match_phrase搜索intro为”工打”,进行拆分后,顺序不一致,所以查询不出。但搜索”打工”就能搜索出

    1
    2
    3
    4
    5
    6
    7
    8
    GET index_test/_search
    {
    "query": {
    "match_phrase": {
    "intro": "工打"
    }
    }
    }
  4. Term查询

    这种查询用于对确切的值进行搜索,它通常用于关键字字段。相比于match,term是代表完全匹配,也就是精确查询,搜索前不会再对搜索词进行分词拆解。
    上述中通过match查询intro为打工人的数据,将查询出两条数据
    但通过term搜索发现一条数据都没有

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    GET index_test/_search
    {
    "query": {
    "term": {
    "intro": {
    "value": "打工人"
    }
    }
    }
    }

    通过analyze查看分词,得到的是[“打”,”工”,”人”],因为term不会进行搜索词的拆分。所以搜索”打工人”并不会搜索出数据。

    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
    POST _analyze
    {
    "text": "打工人"
    }
    {
    "tokens" : [
    {
    "token" : "打",
    "start_offset" : 0,
    "end_offset" : 1,
    "type" : "<IDEOGRAPHIC>",
    "position" : 0
    },
    {
    "token" : "工",
    "start_offset" : 1,
    "end_offset" : 2,
    "type" : "<IDEOGRAPHIC>",
    "position" : 1
    },
    {
    "token" : "人",
    "start_offset" : 2,
    "end_offset" : 3,
    "type" : "<IDEOGRAPHIC>",
    "position" : 2
    }
    ]
    }

    但是,当你要搜索当类型为keyword时,这两种搜索是一致的,因为keyword并不参与分词,text参与分词。
    term还有种用法为terms,等价于mysql 的 in。

    1
    2
    3
    4
    5
    6
    POST index_test/_doc/search
    {
    "query": {
    "terms" : { "intro" : ["打","工"]}
    }
    }
  5. 嵌套类型查询

    Nested (嵌套)类型,是特殊的对象类型,特殊的地方是索引对象数组方式不同,允许数组中的对象各自地进行索引。目的是对象之间彼此独立被查询出来。

    1
    2
    3
    4
    GET index_test/search
    {"query":
    {"nested": {"path": 嵌套对象数组的字段名,加查询语句}}
    }

    例如查询course下的courseDate大于1714359587的数据

    1
    2
    3
    4
    GET index_test/_search
    {"query":
    {"nested": {"path": "course", "query": {"range": { "course.courseDate":{"gt": 1714359587}}}}}
    }
  6. Range查询

    这种查询允许您在指定范围内查找值。
    正常查询为,查询courseDate大于1714359587的数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    GET index_test/_search
    {
    "query": {
    "range": {
    "course.courseDate": {
    "gt": 1714359587
    }
    }
    }
    }

    但例子中使用嵌套类型,所以查询需要修改

    1
    2
    GET index_test/_search
    {"query":{"nested": {"path": "course", "query": {"range": { "course.courseDate":{"gt": 1714359587}}}}}}

    同时我们查询的是一个date类型,写入数据时,写入了字符串和时间戳。只要按照设置的时间格式进行写入和查询,是没有问题的。所以我不不止可以用时间戳进行范围查询,还能用yyyy-MM-dd进行范围查询

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    GET index_test/_search
    {
    "query": {
    "nested": {
    "path": "course", "query": {
    "range": {
    "course.courseDate":{
    "gt": "2024-05-07"}
    }
    }
    }
    }
    }
  7. Exists查询

    exists查询在 Elasticsearch 中用于检查文档中是否存在某个字段或该字段是否具有非空值。这对于基于字段存在性的过滤非常有用。
    通过exists查询name必须有值的数据

    1
    2
    3
    4
    5
    6
    7
    8
    GET index_test/_search
    {
    "query": {
    "exists": {
    "field": "name"
    }
    }
    }
  8. Bool查询

这种查询允许您组合多个查询,并可以通过布尔逻辑(如AND,OR,NOT)来控制查询的结果。must代表true,must_not代表false
通过bool查询name必须有值的数据,且intro不为”打工人”的数据

1
2
3
4
5
GET index_test/_search
{"query": {"bool": {"must": [
{"bool": {"must": [{"exists": {"field": "name"}}]}},
{"bool": {"must_not": [{"match": {"intro": "打工人"}}]}}
]}}}

四、聚合查询

聚合查询是ES中一种强大的数据分析工具,它可以对ES中的数据进行分组、统计、计算等操作。通过聚合查询,用户可以轻松地获取数据的分布情况、统计结果等信息,从而更好地理解数据和分析数据。
Elasticsearch支持强大的聚合功能,允许用户对数据进行分组、计算、统计等操作。常见的聚合类型包括Terms聚合、Avg聚合、Max聚合、Min聚合等。
ES提供了多种类型的聚合查询,包括但不限于:

  1. Metric Aggregations

​ 这种聚合会为文档集计算指标,如平均值、最大值、最小值等。这些聚合通常用于对Bucket Aggregations的结果进 行进一步分析。
​ 平均值查询查询age的平均数,最大值,最小值,统计数据。(avg_salary)可以自定义命名,

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
	GET index_test/_search
{
"size": 0,
"aggs": {
"avg_salary": {
"avg": {
"field": "age"
}
},
"min_salary": {
"min": {
"field": "age"
}
},
"max_salary":{
"max": {
"field": "age"
}
},
"stats_salary": {
"stats": {
"field": "age"
}
}
}
}
  1. Bucket Aggregations

​ 这种聚合会为数据创建桶。每个桶都与一个标准相关联(取决于聚合类型),该标准决定哪些文档属于该桶。例如, 一个terms聚合会为每个唯一字段值创建一个桶,所有具有该字段值的文档都会被放入该桶中。
​ Terms Aggregation关键字: 根据某一项的每个唯一的值来聚合
​ 示例:通过age聚合,只显示3条数据,并进行排序,值要大于1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
GET index_test/_search
{
"size": 0,
"aggs": {
"car_brand": {
"terms": {
"field": "age",
"size": 3,
"order": {
"_count": "asc"
},
"min_doc_count": 1
}
}
}
}
  1. Filter Aggregation关键字

​ 指具体的域和具体的值,可以在Terms Aggregation 的基础上进行了过滤,只对特定的值进行了聚合
​ 示例:先聚合两个,分别为intro包含”人” intro_str包含”business”的。得到的两个桶进行统计

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
{
"took" : 6,
"timed_out" : false,
"_shards" : {
"total" : 6,
"successful" : 6,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "index_test",
"_type" : "_doc",
"_id" : "id_2",
"_score" : 1.0,
"_source" : {
"name" : "小明",
"age" : 25,
"intro" : "打工人",
"intro_str" : "Migrant worker",
"course" : [
{
"courseName" : "打工人必备技巧",
"teacherName" : "小亮",
"courseDate" : "2024-04-30",
"courseIntroduction" : "打工人必备技巧。",
"isSuccess" : true
},
{
"courseName" : "天选打工人",
"teacherName" : "杰克",
"courseDate" : 1715138087,
"courseIntroduction" : "天选打工人",
"isSuccess" : false
}
]
}
},
{
"_index" : "index_test",
"_type" : "_doc",
"_id" : "id_1",
"_score" : 1.0,
"_source" : {
"name" : "张三",
"age" : 20,
"intro" : "我是一名粉刷匠,粉刷本领强",
"intro_str" : "The business includes painting walls, touching up paint, cutting bricks",
"course" : [
{
"courseName" : "论粉刷墙壁的重要性",
"teacherName" : "李四",
"courseDate" : "2024-01-04",
"courseIntroduction" : "墙面粉刷是对空间美学的一种诠释。通过巧妙的色彩搭配和质感处理,可以营造出不同的空间氛围和风格,使得室内空间更加符合人们的审美需求和生活习惯。",
"isSuccess" : true
},
{
"courseName" : "粉刷的三百六十五种技巧",
"teacherName" : "李四",
"courseDate" : 1714359588,
"courseIntroduction" : "《粉刷的三百六十五种技巧》是一本全面而详尽的粉刷技巧指南,适合从初学者到专业粉刷工的所有读者。这本书将带您深入了解粉刷的各个方面,让您掌握粉刷的艺术,为家庭和工作场所带来焕然一新的面貌。",
"isSuccess" : false
}
]
}
},
{
"_index" : "index_test",
"_type" : "_doc",
"_id" : "id_3",
"_score" : 1.0,
"_source" : {
"name" : "小A",
"age" : 17,
"intro" : "打工人",
"intro_str" : "Migrant worker",
"course" : [
{
"courseName" : "打工人必备技巧",
"teacherName" : "小亮",
"courseDate" : "2024-04-25",
"courseIntroduction" : "打工人必备技巧。",
"isSuccess" : false
},
{
"courseName" : "粉刷的三百六十五种技巧",
"teacherName" : "李四",
"courseDate" : 1714359588,
"courseIntroduction" : "《粉刷的三百六十五种技巧》是一本全面而详尽的粉刷技巧指南,适合从初学者到专业粉刷工的所有读者。这本书将带您深入了解粉刷的各个方面,让您掌握粉刷的艺术,为家庭和工作场所带来焕然一新的面貌。",
"isSuccess" : true
}
]
}
}
]
}
}
GET index_test/_search
{
"size": 0,
"aggs": {
"cars": {
"filters": {
"filters": {
"colorBucket":{
"match":{
"intro":"人"
}
},
"brandBucket":{
"match":{
"intro_str":"business"
}
}
}
},
"aggs": {
"stats_salary": {
"stats": {
"field": "age"
}
}
}
}
}
}
{
"took" : 6,
"timed_out" : false,
"_shards" : {
"total" : 6,
"successful" : 6,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"cars" : {
"buckets" : {
"brandBucket" : {
"doc_count" : 1,
"stats_salary" : {
"count" : 1,
"min" : 20.0,
"max" : 20.0,
"avg" : 20.0,
"sum" : 20.0
}
},
"colorBucket" : {
"doc_count" : 2,
"stats_salary" : {
"count" : 2,
"min" : 17.0,
"max" : 25.0,
"avg" : 21.0,
"sum" : 42.0
}
}
}
}
}
}
  1. Range Aggregation关键字

​ 根据用户传递的范围参数作为桶,进行相应的聚合。在同一请求中,请求传递多组范围,每组范围作为一个桶
​ 示例:通过age的范围进行分组

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
GET index_test/_search
{
"size": 0,
"aggs": {
"age_range": {
"range": {
"field": "age",
"ranges": [
{
"key": "<18",
"to":18
},
{
"key": "18~22",
"from": 18,
"to": 22
},
{
"key": ">22",
"from": 22
}
]
}
}
}
}

五、设置查询出的结果

在查询时,可以通过设置size参数来控制返回的结果数量。默认情况下,Elasticsearch只返回前10条结果。
示例:将输出20条结果

1
2
3
4
5
6
7
GET /index_test/_search
{
"size": 20,
"query": {
"match_all": {}
}
}

可以通过设置sort参数来对字段进行排序。
示例:将age进行倒叙排序

1
2
3
4
5
6
7
8
9
10
11
12
GET index_test/_search
{
"query": {
"match_all": {}
},"sort": [
{
"age": {
"order": "desc"
}
}
]
}

_source:当你对Elasticsearch进行搜索查询时,默认情况下,返回的搜索结果中会包含匹配文档的_source字段。这使得你可以查看存储在Elasticsearch中的实际文档内容。
示例:只输出name和age

1
2
3
4
5
6
7
8
GET index_test/_search
{
"query": {
"match_all": {}
},"_source": ["name","age"]
}


Elasticsearch高亮处理:es中的高亮处理是一种功能,它允许用户在执行搜索查询时,将搜索结果中与查询匹配的部分以特殊的方式显示出来,通常是加粗、变色或其他视觉上的区分。这种高亮显示有助于用户快速识别查询关键词在文档中的位置,提高搜索体验。

六、总结

Elasticsearch的Query DSL提供了一种强大且灵活的方式来执行各种复杂的查询。通过组合不同的查询类型和布尔逻辑,您可以创建出满足特定需求的查询。

请注意,以上示例和解释是基于Elasticsearch的通用使用情况和理解。在实际应用中,可能需要根据自己的数据模型和查询需求进行调整。

希望这份文档能帮助理解Elasticsearch的查询功能,并为实际应用中使用Elasticsearch提供指导。


Elasticsearch查询
https://flyfishs.top/2024/04/29/Elasticsearch查询/
作者
飞鱼
发布于
2024年4月29日
许可协议