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}]"}
    1098 views