Skip to content

Commit eb0a03f

Browse files
committed
新增笔记:Elasticsearch DSL查询
1 parent 68a67e5 commit eb0a03f

File tree

11 files changed

+349
-3
lines changed

11 files changed

+349
-3
lines changed
Loading
Loading
Loading
Loading
Loading
Loading
Loading

基础笔记/数据库/Elasticsearch/index.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@
55
[Elasticsearch索引管理](./subfile/_2Elasticsearch索引管理.md)
66

77
[Elasticsearch索引映射](_4Elasticsearch索引字段映射.md)
8+
9+
[Elasticsearch文档管理](./subfile/_3Elasticsearch文档管理.md)
10+
11+
[Elasticsearch查询](./subfile/_5DSL查询.md)

基础笔记/数据库/Elasticsearch/subfile/_2Elasticsearch索引管理.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ PUT /{index_name}/_mapping
183183
184184
字段映射功能会在后面文章中详细介绍。
185185
186+
可以参考:[Elasticsearch索引字段映射(mapping)](./_4Elasticsearch索引字段映射.md)
187+
186188
### 3.3 修改aliases配置
187189
188190
字段别名功能会在后面文章中详细介绍。

基础笔记/数据库/Elasticsearch/subfile/_3Elasticsearch文档管理.md

Lines changed: 94 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,12 @@ POST /{index_name}/_doc/{id}
3434

3535
## 二. 更新文档
3636

37+
### 2.1 根据ID替换文档
38+
39+
**`PUT` 请求**:通常用于完整替换文档。如果只提供了部分字段,原文档中未提及的字段会被删除。比如原文档有 `field1``field2``field3`,使用 `PUT` 请求只更新 `field1`,那么更新后文档将只包含 `field1``field2``field3` 会被删除。
40+
3741
```bash
38-
PUT /{index_name}/_doc/{id}
42+
PUT /{index_name}/_doc/{document_id}
3943
{
4044
...
4145
}
@@ -44,9 +48,81 @@ PUT /{index_name}/_doc/{id}
4448
- index_name:索引名称
4549
- id:文档ID,必填。
4650

51+
例如:
52+
53+
```json
54+
PUT /employee/_doc/7
55+
{
56+
"name": "王五",
57+
"age": 27
58+
}
59+
```
60+
61+
### 2.2 根据ID部分更新文档
62+
63+
部分更新允许你只更新文档中的某些字段,而不影响其他字段。以下是一个使用 `POST` 请求进行部分更新的示例:
64+
65+
```json
66+
POST /{index_name}/_update/{document_id}
67+
{
68+
"doc": {
69+
"field1": "new_value1",
70+
"field2": "new_value2"
71+
}
72+
}
73+
```
74+
75+
![](../images/26.png)
76+
77+
### 2.3 根据查询条件更新文档
78+
79+
#### 2.3.1 案例一:更新部分文档name字段
80+
81+
例如我需要更新所有 `age>18` 的数据,在 `name` 字段后面增加一个统一后缀“(成人)”:
82+
83+
```java
84+
POST /employee/_update_by_query
85+
{
86+
"query": {
87+
"range": {
88+
"age": {
89+
"gt": 18
90+
}
91+
}
92+
},
93+
"script": {
94+
"source": "ctx._source.Name = ctx._source.Name + '(成人)'",
95+
"lang": "painless"
96+
}
97+
}
98+
```
99+
100+
**解释:**
101+
102+
- **`_update_by_query`**:这是 Elasticsearch 提供的用于批量更新满足特定查询条件的文档的 API。
103+
- **`query`**:指定更新操作的筛选条件。这里使用 `range` 查询筛选出 `age` 大于 18 的文档。
104+
- **`script`**:使用 Painless 脚本对符合条件的文档进行更新。`ctx._source` 表示当前文档的源数据,通过 `ctx._source.Name = ctx._source.Name + '(成人)'` 语句在 `Name` 字段后面添加 “(成人)” 后缀。
105+
106+
![](../images/27.png)
107+
108+
#### 2.3.2 案例二:删除文档中的某个字段
109+
110+
```java
111+
POST /employee/_update_by_query
112+
{
113+
"query": {
114+
"match_all": {}
115+
},
116+
"script": {
117+
"source": "if (ctx._source.containsKey('Name')) { ctx._source.remove('Name') }",
118+
"lang": "painless"
119+
}
120+
}
121+
```
122+
47123
## 三. 删除文档
48124

49-
##
125+
### 3.1 根据ID删除文档
50126

51127
```bash
52128
DELETE /{index_name}/_doc/{id}
@@ -57,7 +133,22 @@ DELETE /{index_name}/_doc/{id}
57133

58134
![](../images/8.png)
59135

60-
## 四. 查询文档
136+
### 3.2 根据查询条件删除文档
137+
138+
删除 `age>60` 的文档:
139+
140+
```JSON
141+
POST /employee/_delete_by_query
142+
{
143+
"query": {
144+
"range": {
145+
"age": {
146+
"gt": 60
147+
}
148+
}
149+
}
150+
}
151+
```
61152

62153

63154

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
# DSL查询
2+
3+
> 本文参考至:[ES详解 - 入门:查询和聚合的基础使用 | Java 全栈知识体系](https://pdai.tech/md/db/nosql-es/elasticsearch-x-usage.html)
4+
5+
## 一. 基础查询
6+
7+
### 1.1 查询所有(match_all)
8+
9+
`match_all`表示查询所有的数据,`sort`即按照什么字段排序
10+
11+
```bash
12+
GET /{index_name}/_search
13+
{
14+
"query": {
15+
"match_all": {}
16+
},
17+
"sort": [
18+
{
19+
"account_number": "asc"
20+
}
21+
]
22+
}
23+
```
24+
25+
![](../images/21.png)
26+
27+
相关字段解释
28+
29+
- `took`:Elasticsearch运行查询所花费的时间(以毫秒为单位)
30+
- `timed_out`:搜索请求是否超时
31+
- `_shards`:搜索了多少个分片,以及成功,失败或跳过了多少个碎片的细目分类。
32+
- `max_score`:找到的最相关文档的分数
33+
- `hits.total.value`:找到了多少个匹配的文档
34+
- `hits.sort`:文档的排序位置(不按相关性得分排序时)
35+
- `hits._score`:文档的相关性得分(使用match_all时不适用)
36+
37+
### 1.2 分页查询(from+size)
38+
39+
本质上就是from和size两个字段
40+
41+
```bash
42+
GET /{index_name}/_search
43+
{
44+
"query": {
45+
"match_all": {}
46+
},
47+
"sort": [
48+
{
49+
"account_number": "asc"
50+
}
51+
],
52+
"from": 2,
53+
"size": 5
54+
}
55+
```
56+
57+
在 Elasticsearch 的查询请求中,`from``size` 这两个参数主要用于实现分页功能。下面为你详细解释这两个参数在你给出的查询中的作用:
58+
59+
- `from` 参数明确了查询结果起始的偏移量,也就是跳过前 `from` 条数据,从第 `from+1` 条结果开始返回。**它的默认值是 0,跳过前0条数据,从第1条结果返回**。在你的查询里,`from` 的值设定为 2,这表明 Elasticsearch 会跳过前 2 条结果,从第 3 条结果开始返回。
60+
61+
- `size` 参数指定了查询结果返回的最大文档数量。**它的默认值为 10,即默认返回 10 条结果**。在你的查询中,`size` 的值为 5,这就表示 Elasticsearch 只会返回至多 5 条结果。
62+
63+
### 1.3 指定字段查询(match)
64+
65+
如果要在字段中搜索特定字词,可以使用`match`; 如下语句将查询address 字段中包含 mill 或者 lane的数据
66+
67+
```bash
68+
GET /{index_name}/_search
69+
{
70+
"query": {
71+
"match": {
72+
"address": "mill lane"
73+
}
74+
}
75+
}
76+
```
77+
78+
由于ES底层是按照分词索引的,所以上述查询结果是address 字段中包含 mill 或者 lane的数据:
79+
80+
![](../images/22.png)
81+
82+
### 1.4 查询段落匹配(match_phrase)
83+
84+
如果我们希望查询的条件是 address 字段中包含 "mill lane",则可以使用`match_phrase`
85+
86+
```bash
87+
GET /{index_name}/_search
88+
{
89+
"query": {
90+
"match_phrase": {
91+
"address": "mill lane"
92+
}
93+
}
94+
}
95+
```
96+
97+
![](../images/23.png)
98+
99+
## 二. 聚合查询
100+
101+
### 2.1 简单聚合
102+
103+
比如我们希望计算出 account 每个州的统计数量,使用`aggs`关键字对`state`字段聚合,被聚合的字段无需对分词统计,所以使用`state.keyword`对整个字段统计
104+
105+
```bash
106+
GET /{index_name}/_search
107+
{
108+
"size": 0,
109+
"aggs": {
110+
"group_by_state": {
111+
"terms": {
112+
"field": "state.keyword"
113+
}
114+
}
115+
}
116+
}
117+
```
118+
119+
因为无需返回条件的具体数据, 所以设置size=0,返回hits为空。
120+
121+
`doc_count` 表示 bucket 中每个州的数据条数。
122+
123+
![](../images/24.png)
124+
125+
### 2.2 嵌套聚合
126+
127+
ES还可以处理个聚合条件的嵌套。
128+
129+
比如承接上个例子, 计算每个州的平均结余。涉及到的就是在对state分组的基础上,嵌套计算avg(balance):
130+
131+
```bash
132+
GET /{index_name}/_search
133+
{
134+
"size": 0,
135+
"aggs": {
136+
"group_by_state": {
137+
"terms": {
138+
"field": "state.keyword"
139+
},
140+
"aggs": {
141+
"average_balance": {
142+
"avg": {
143+
"field": "balance"
144+
}
145+
}
146+
}
147+
}
148+
}
149+
}
150+
```
151+
152+
![](../images/25.png)
153+
154+
- `"group_by_state"`:这是聚合操作的名称,可以自定义,用于标识这个聚合操作。
155+
- `"terms"`:这是一种聚合类型,被称为 “词条聚合”。它会根据指定字段的值对文档进行分组,每个不同的值会形成一个分组。
156+
- `"field": "state.keyword"`:指定用于分组的字段为 `state.keyword``keyword` 类型通常用于精确匹配,在 Elasticsearch 中,对字符串字段进行聚合时,通常使用 `.keyword` 子字段以确保精确分组。
157+
- 嵌套的aggs:表示在每个分组内部再进行一次聚合操作。
158+
- `"average_balance"`:这是嵌套聚合操作的名称。
159+
- `"avg"`:这是一种聚合类型,被称为 “平均值聚合”,用于计算指定字段的平均值。
160+
- `"field": "balance"`:指定用于计算平均值的字段为 `balance`
161+
162+
### 2.3 对聚合结果排序
163+
164+
可以通过在aggs中对嵌套聚合的结果进行排序
165+
166+
比如承接上个例子, 对嵌套计算出的avg(balance),这里是average_balance,进行排序
167+
168+
```json
169+
GET /{index_name}/_search
170+
{
171+
"size": 0,
172+
"aggs": {
173+
"group_by_state": {
174+
"terms": {
175+
"field": "state.keyword",
176+
"order": {
177+
"average_balance": "desc"
178+
}
179+
},
180+
"aggs": {
181+
"average_balance": {
182+
"avg": {
183+
"field": "balance"
184+
}
185+
}
186+
}
187+
}
188+
}
189+
}
190+
```
191+
192+
- `"group_by_state"`:这是聚合操作的名称,可自行定义,用于标识该聚合操作。
193+
- `"terms"`:属于 “词条聚合” 类型,其作用是依据指定字段的值对文档进行分组,每个不同的值会形成一个分组。
194+
- `"field": "state.keyword"`:指定用于分组的字段为 `state.keyword`。在 Elasticsearch 里,`keyword` 类型常用于精确匹配,对字符串字段进行聚合时,通常使用 `.keyword` 子字段以确保精确分组。
195+
- `"order"`:该参数用于对分组结果进行排序。
196+
- `"average_balance": "desc"`:表示按照 `average_balance` 这个嵌套聚合的结果进行降序排序。也就是说,分组会根据每个州对应的平均余额从高到低排列。
197+
- 嵌套的aggs:表示在每个分组内部再进行一次聚合操作。
198+
- `"average_balance"`:这是嵌套聚合操作的名称。
199+
- `"avg"`:属于 “平均值聚合” 类型,用于计算指定字段的平均值。
200+
- `"field": "balance"`:指定用于计算平均值的字段为 `balance`
201+
202+
## 三. 复合查询
203+
204+
在查询中会有多种条件组合的查询,在ElasticSearch中叫复合查询。它提供了5种复合查询方式:**bool query(布尔查询)****boosting query(提高查询)****constant_score(固定分数查询)****dis_max(最佳匹配查询)****function_score(函数查询)**
205+
206+
### 3.1 bool query(布尔查询)
207+
208+
Bool查询语法有以下特点
209+
210+
- 子查询可以任意顺序出现
211+
- 可以嵌套多个查询,包括bool查询
212+
- 如果bool查询中没有must条件,should中必须至少满足一条才会返回结果。
213+
214+
bool查询包含四种操作符,分别是must,should,must_not,filter。他们均是一种数组,数组里面是对应的判断条件。
215+
216+
- `must`: 必须匹配。贡献算分
217+
- `must_not`:过滤子句,必须不能匹配,但不贡献算分
218+
- `should`: 选择性匹配,至少满足一条。贡献算分
219+
- `filter`: 过滤子句,必须匹配,但不贡献算分
220+
221+
一些例子:
222+
223+
```sql
224+
GET /{index_name}/_search
225+
{
226+
"query": {
227+
"bool" : {
228+
"must" : {
229+
"term" : { "user.id" : "kimchy" }
230+
},
231+
"filter": {
232+
"term" : { "tags" : "production" }
233+
},
234+
"must_not" : {
235+
"range" : {
236+
"age" : { "gte" : 10, "lte" : 20 }
237+
}
238+
},
239+
"should" : [
240+
{ "term" : { "tags" : "env1" } },
241+
{ "term" : { "tags" : "deployed" } }
242+
],
243+
"minimum_should_match" : 1,
244+
"boost" : 1.0
245+
}
246+
}
247+
}
248+
```
249+

0 commit comments

Comments
 (0)