ElasticSearch 查詢
===
---
# Query DSL
Query DSL (Domain Specific Language) 提供基於JSON來定義查詢。由兩種類型的子句組成:
---
- Leaf query clauses (簡單查詢)
- 葉查詢子句查找特定字段中的特定值,例如 match, term 或 range 查詢。這些查詢可以單獨使用。
- Compound query clauses (複雜查詢)
- 複合查詢子句包裝其他葉查詢或複合查詢,用於以邏輯方式組合多個查詢(例如bool)
---
## 分詞
把全文字轉換成一系列單詞(term/token)的過程叫做分詞
https://www.gushiciku.cn/pl/pYl8/zh-tw
---
```json=
GET _analyze
{
"analyzer": "standard",
"text": "this is a test"
}
```
:::info
"this is a test" 進行分詞 => ["this","is","a","test"]
:::
---
分詞系統使用特殊符號進行分隔
標點符號可能是單詞的一部分取決於它的位置:
```json=
GET /_analyze?tokenizer=standard
You're my 'favorite'.
```
:::info
["You're","my","favorite"]
:::
---
## 資料欄位型別
---
### text 和 keyword 區別
- text 進行分詞
- keyword 不進行分詞
---
```json=
GET /my-index/
{
"my-index" : {
"aliases" : { },
"mappings" : {
"properties" : {
"message" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
```
- 欄位message 為 text
- 欄位message.keyword 為 keyword
---
# Search API
---
## Match query
- 提供的文本,數字,日期或布爾值匹配的文檔。
- 匹配之前對提供的文本進行分析。
- 該match查詢是用於執行全文搜索的標準查詢,其中包括模糊匹配的選項。
---
## Term query
- 提供的字段中包含確切詞語的文檔。
- 您可以使用term查詢根據精確的值(例如價格,產品ID或用戶名)查找文檔。
:::info
避免term對text字段使用查詢。
默認情況下,Elasticsearch更改text字段的值,作為analysis的一部分。
這會使查找text字段值的精確匹配變得困難。
要搜索text字段值,請改用match查詢。
:::
<!-- .element: class="alert" style="font-size: 24px;" -->
---
## match和term的區別
- match 進行分詞
- term 不進行分詞
---
範例
```json=
#建立資料
POST my-index/_doc/
{
"message" : "this is a test"
}
```
分詞結果["this","is","a","test"]
---
match 匹配成功
```json=
#match 查詢
GET /my-index/_search
{
"query": {
"match": {
"message":"this is a test"
}
}
}
```
- match分詞後["this","is","a","test"],任一條件匹配即可
---
term 匹配失敗
```json=
#term 查詢
GET /my-index/_search
{
"query": {
"term": {
"message":"this is a test"
}
}
}
```
- term不進行分詞,將["this is a test"]視為一個分詞條件
- 若要使term匹配,則要使用message.keyword
---
1. term查詢keyword欄位,需要完全匹配才可以
2. term查詢text欄位,term查詢條件必須是text欄位分詞後
3. match查詢text欄位,只要match的分詞結果和text的分詞結果有相同就匹配
4. match查詢keyword欄位,ES使用Term Analyzer,與term查詢一致
---
## match_all
搜尋全部文檔
```json=
GET /my-index/_search
{
"query": {
"match_all": {}
}
}
```
---
## multi_match
(match query)允許多欄位查詢
```json=
GET /my-index/_search
{
"query": {
"multi_match": {
"query":"this is a",
"fields": ["message","name"]
}
}
}
```
---
## match_phrase
match_phrase : 欄位分詞中都包含,而且順序必須相同,而且必須都是連續的
```json=
GET /my-index/_search
{
"query": {
"match_phrase": {
"message":"this is a test"
}
}
}
```
---
## match_phrase_prefix
match_phrase_prefix 和match_phrase類似,只不過match_phrase_prefix 支援最後一個term字首比對
```json=
GET /my-index/_search
{
"query": {
"match_phrase_prefix": {
"message":"this is a te"
}
}
}
```
---
## range query
```json=
GET /transaction_message-*/_search
{
"query": {
"range": {
"@timestamp": {
"gte": "now-1d/d",
"lt": "now/d"
}
}
}
}
```
---
```json=
GET /transaction_message-*/_search
{
"query": {
"range": {
"timestamp": {
"time_zone": "+08:00",
"gte": "2020-05-01T00:00:00",
"lte": "now"
}
}
}
}
```
---
# Bool query
- Bool 查詢可以把任一個簡單查詢組合在一起,使用must、should、must_not 關鍵字處理。
|Bool query|邏輯運算式|
|---|---|
|must|AND|
|should|OR|
|must_not|NOT|
---
```json=
GET /my-index/_search
{
"query": {
"bool": {
"must": [
{
"bool": {
"should": [
{
"match":{"message":"this"}
},
{
"match":{"message":"is"}
}
],
"must_not": [
{
"match":{"message":"test"}
}
]
}
},
{
"bool": {
"must": [
{
"match":{"message":"shark"}
}
]
}
}
]
}
}
}
```
<!-- .slide: style="font-size: 26px;" -->
---
## Query and filter context
- 查詢子句的使用行為取決於它是在查詢上下文中、還是在篩選上下文中使用:
1. Query DSL:
- 查詢除了確定文檔是否匹配外,並且計算一個_score,表示文檔相對於其他文檔的匹配程度。
2. Filter DSL:
- 查詢文檔是否與此查詢子句匹配,並不計算任何分數,因此篩選上下文主要用於篩選結構化資料,而Elasticsearch會自動緩存常用的篩選器,以加快性能。
<!-- .slide: style="font-size: 32px;" -->
---
```json=
GET /transaction_message-*/_search
{
"query": {
"bool": {
"must": [
{
"term":{"message.mti.keyword":"0800"}
}
],
"filter": [
{
"range": {
"@timestamp": {
"gte": "now-1d/d",
"lt": "now/d"
}
}
}
]
}
}
}
```
---
## From/Size
- 在請求體中的查詢字段允許使用查詢DSL定義一個查詢。透過From和Size參數控制分頁,size參數允許你配置返回結果的最大數量。
注意: from+size不能超過index.max_result_window選項,默認值是10000
---
```json=
#第1頁,取10筆
GET /transaction_message-*/_search
{
"from": 1,
"size": 10,
"query": {
"bool": {
"must": [
{
"term":{"message.mti.keyword":"0800"}
}
],
"filter": [
{
"range": {
"@timestamp": {
"gte": "now-1d/d",
"lt": "now/d"
}
}
}
]
}
}
}
```
<!-- .slide: style="font-size: 26px;" -->
---
## Sort
允許添加一個或者多個排序,每個排序都可以指定排序規則。使用字段名的排序是定義在字段層面的,使用_score表示按得分排序,使用_doc表示按索引時間的順序排序。
```json=
GET /transaction_message-*/_search
{
"from": 1,
"size": 10,
"sort": [
{"message.mti.keyword": "desc"},
"_score"
],
"query": {
"bool": {
"filter": [
{
"range": {
"@timestamp": {
"gte": "now-1d/d",
"lt": "now/d"
}
}
}
]
}
}
}
```
<!-- .slide: style="font-size: 32px;" -->
---
## Sort Values
排序值也作為返回結果的一部分返回
|Sort|以order選項控制|
|--|--|
|asc|升序|
|desc|降序|
|參數| 說明|
|--|--|
|min| 數組中最小的值作為排序值
|max| 數組中最大的值作為排序值
|sum| 數組中所有元素的總和作為排序值
|avg| 數組中所有元素的平均值作為排序值
|median| 使用所有值的中位數作為排序值
<!-- .slide: style="font-size: 32px;" -->
---
```json=
POST price/_doc/
{
"name": "bbb",
"price" : [1,10,51,63,20,100]
}
GET /price/_search
{
"sort": [
{
"price": {
"order": "desc",
"mode": "min"
}
}
]
}
```
<!-- .slide: style="font-size: 26px;" -->
---
## Query string query
查詢使用語法運算符(例如AND 、 NOT)來解析和拆分提供的查詢字符串。
[說明](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html)
---
```json=
GET tb_inc_internal_sync-*/_search
{
"size": 1,
"query": {
"query_string":{
"analyze_wildcard":true,
"query":"tran_code:05 AND card_plan:M AND setl_flag:9"
}
}
}
```
<!-- .slide: style="font-size: 26px;" -->
---
### Wildcards 通配符
使用 ? 代表1個字元
使用 * 代表0到多 個字元
---
### Regular expression 正規表示式
在反斜線內使用正規表示式
name:/joh?n(ath[oa]n)/
---
### Fuzziness 模糊查詢
可以搜尋相近但不完全不正確的詞
查找最大兩個變化的所有術語,其中變化是單個字符的插入,刪除或替換,或者兩個相鄰字符的轉置。
```json=
quikc~ brwn~ foks~
```
---
預設的編輯距離是2,但是編輯距離1應該足以捕捉所有人類拼寫錯誤的80%。可以指定為:
```json=
quikc~1
```
---
## Ranges
可以為日期,數字或字串指定範圍。
包含範圍用方括號[min TO max]
排除範圍用花括號{min TO max}
---
```json=
2012年所有天數:
date:[2012-01-01 TO 2012-12-31]
數字1..5
count:[1至5]
於alpha和omega之間的tag,但不包括alpha和omega:
tag:{alpha TO omega}
10以上的數字
count:[10 TO *]
2012年之前的日期
date:{* TO 2012-01-01}
數字1到5但不包含5
count:[1 TO 5}
```
<!-- .slide: style="font-size: 26px;" -->
---
# SQL access
---
## SQL REST API
使用 SQL REST API 進行查詢
Kibana:
```json=
POST /_sql?format=json
{
"query": """SELECT * FROM "tb_inc_internal_sync-*" ORDER BY tran_code DESC LIMIT 1"""
}
```
<!-- .slide: style="font-size: 26px;" -->
---
## SQL Translate API
將API 語法 轉換為Elasticsearch 原生語法
```json=
POST /_sql/translate
{
"query": """SELECT * FROM "tb_inc_internal_sync-*" where tran_code.keyword='05' ORDER BY tran_code DESC LIMIT 1""",
"fetch_size": 10
}
```
<!-- .slide: style="font-size: 26px;" -->
---
# 敬請指教
----
{"metaMigratedAt":"2023-06-15T23:50:18.828Z","metaMigratedFrom":"Content","title":"ElasticSearch 查詢","breaks":true,"contributors":"[{\"id\":\"565617f1-fa63-410c-9fb9-a9278632bb7a\",\"add\":9764,\"del\":2573},{\"id\":\"be103b27-62d0-4db7-b9c6-0255f1d0f865\",\"add\":1107,\"del\":234}]"}