本篇爲學習DSL時作的筆記,適合ES新手,大佬請略過~nginx
Query DSL又叫查詢表達式,是一種很是靈活又富有表現力的查詢語言,採用JSON接口的方式實現豐富的查詢,並使你的查詢語句更靈活、更精確、更易讀且易調試數組
Elasticsearch(如下簡稱ES)中的數據檢索分爲兩種狀況:查詢和過濾。緩存
Query查詢會對檢索結果進行評分,注重的點是匹配程度,例如檢索「運維咖啡吧」與文檔的標題有多匹配,計算的是查詢與文檔的相關程度,計算完成以後會算出一個評分,記錄在_score
字段中,並最終按照_score
字段來對全部檢索到的文檔進行排序app
Filter過濾不會對檢索結果進行評分,注重的點是是否匹配,例如檢索「運維咖啡吧」是否匹配文檔的標題,結果只有匹配或者不匹配,由於只是對結果進行簡單的匹配,因此計算起來也很是快,而且過濾的結果會被緩存到內存中,性能要比Query查詢高不少運維
一個最簡單的DSL查詢表達式以下:elasticsearch
GET /_search { "query":{ "match_all": {} } }
**/_search** 查找整個ES中全部索引的內容性能
query 爲查詢關鍵字,相似的還有aggs
爲聚合關鍵字學習
match_all 匹配全部的文檔,也能夠寫match_none
不匹配任何文檔url
返回結果:unix
{ "took": 6729, "timed_out": false, "num_reduce_phases": 6, "_shards": { "total": 2611, "successful": 2611, "skipped": 0, "failed": 0 }, "hits": { "total": 7662397664, "max_score": 1, "hits": [ { "_index": ".kibana", "_type": "doc", "_id": "url:ec540365d822e8955cf2fa085db189c2", "_score": 1, "_source": { "type": "url", "updated_at": "2018-05-09T07:19:46.075Z", "url": { "url": "/app/kibana", "accessCount": 0, "createDate": "2018-05-09T07:19:46.075Z", "accessDate": "2018-05-09T07:19:46.075Z" } } }, ...省略其餘的結果... ] } }
took: 表示咱們執行整個搜索請求消耗了多少毫秒
timed_out: 表示本次查詢是否超時
這裏須要注意當timed_out
爲True時也會返回結果,這個結果是在請求超時時ES已經獲取到的數據,因此返回的這個數據可能不完整。
且當你收到timed_out
爲True以後,雖然這個鏈接已經關閉,但在後臺這個查詢並無結束,而是會繼續執行
**_shards:** 顯示查詢中參與的分片信息,成功多少分片失敗多少分片等
hits: 匹配到的文檔的信息,其中total
表示匹配到的文檔總數,max_score
爲文檔中全部_score
的最大值
hits中的hits
數組爲查詢到的文檔結果,默認包含查詢結果的前十個文檔,每一個文檔都包含文檔的_index
、_type
、_id
、_score
和_source
數據
結果文檔默認狀況下是按照相關度(_score)進行降序排列,也就是說最早返回的是相關度最高的文檔,文檔相關度意思是文檔內容與查詢條件的匹配程度,上邊的查詢與過濾中有介紹
上邊的查詢會搜索ES中的全部索引,但咱們一般狀況下,只須要去固定一個或幾個索引中搜索就能夠了,搜索所有無疑會形成資源的浪費,在ES中能夠經過如下幾種方法來指定索引
ops-coffee-nginx-2019.05.15
爲索引名字GET /ops-coffee-nginx-2019.05.15/_search
以上表示在ops-coffee-nginx-2019.05.15
索引下查找數據
GET /ops-coffee-nginx-2019.05.15,ops-coffee-nginx-2019.05.14/_search
GET /ops-coffee-nginx-*/_search
固然這裏也能夠用逗號分割多個匹配索引
上邊有說到查詢結果hits
默認只展現10個文檔,那咱們如何查詢10個之後的文檔呢?ES中給了size
和from
兩個參數
size: 設置一次返回的結果數量,也就是hits
中的文檔數量,默認爲10
from: 設置從第幾個結果開始日後查詢,默認值爲0
GET /ops-coffee-nginx-2019.05.15/_search { "size": 5, "from": 10, "query":{ "match_all": {} } }
以上查詢就表示查詢ops-coffee-nginx-2019.05.15
索引下的全部數據,並會在hits
中顯示第11到第15個文檔的數據
上邊有用到一個match_all
的全文查詢關鍵字,match_all
爲查詢全部記錄,經常使用的查詢關鍵字在ES中還有如下幾個
最簡單的查詢,下邊的例子就表示查找host
爲ops-coffee.cn
的全部記錄
GET /ops-coffee-2019.05.15/_search { "query":{ "match": { "host":"ops-coffee.cn" } } }
在多個字段上執行相同的match查詢,下邊的例子就表示查詢host
或http_referer
字段中包含ops-coffee.cn
的記錄
GET /ops-coffee-2019.05.15/_search { "query":{ "multi_match": { "query":"ops-coffee.cn", "fields":["host","http_referer"] } } }
能夠在查詢裏邊使用AND或者OR來完成複雜的查詢,例如:
GET /ops-coffee-2019.05.15/_search { "query":{ "query_string": { "query":"(a.ops-coffee.cn) OR (b.ops-coffee.cn)", "fields":["host"] } } }
以上表示查找host爲a.ops-coffee.cn
或者b.ops-coffee.cn
的全部記錄
也能夠用下邊這種方式組合更多的條件完成更復雜的查詢請求
GET /ops-coffee-2019.05.14/_search { "query":{ "query_string": { "query":"host:a.ops-coffee.cn OR (host:b.ops-coffee.cn AND status:403)" } } }
以上表示查詢(host爲a.ops-coffee.cn
)或者是(host爲b.ops-coffee.cn
且status爲403)的全部記錄
與其像相似的還有個simple_query_string的關鍵字,能夠將query_string
中的AND或OR用+
或|
這樣的符號替換掉
term能夠用來精確匹配,精確匹配的值能夠是數字、時間、布爾值或者是設置了not_analyzed
不分詞的字符串
GET /ops-coffee-2019.05.14/_search { "query":{ "term": { "status": { "value": 404 } } } }
term對輸入的文本不進行分析,直接精確匹配輸出結果,若是要同時匹配多個值可使用terms
GET /ops-coffee-2019.05.14/_search { "query": { "terms": { "status":[403,404] } } }
range用來查詢落在指定區間內的數字或者時間
GET /ops-coffee-2019.05.14/_search { "query": { "range":{ "status":{ "gte": 400, "lte": 599 } } } }
以上表示搜索全部狀態爲400到599之間的數據,這裏的操做符主要有四個gt
大於,gte
大於等於,lt
小於,lte
小於等於
當使用日期做爲範圍查詢時,咱們須要注意下日期的格式,官方支持的日期格式主要有兩種
GET /ops-coffee-2019.05.14/_search { "query": { "range": { "@timestamp": { "gte": 1557676800000, "lte": 1557680400000, "format":"epoch_millis" } } } }
GET /ops-coffee-2019.05.14/_search { "query": { "range":{ "@timestamp":{ "gte": "2019-05-13 18:30:00", "lte": "2019-05-14", "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd", "time_zone": "+08:00" } } } }
一般更推薦用這種日期字符串的方式,看起來比較清晰,日期格式能夠按照本身的習慣輸入,只須要format
字段指定匹配的格式,若是格式有多個就用||
分開,像例子中那樣,不過我更推薦用一樣的日期格式
若是日期中缺乏年月日這些內容,那麼缺乏的部分會用unix的開始時間(即1970年1月1日)填充,當你將"format":"dd"
指定爲格式時,那麼"gte":10
將被轉換成1970-01-10T00:00:00.000Z
elasticsearch中默認使用的是UTC時間,因此咱們在使用時要經過time_zone
來設置好時區,以避免出錯
一般咱們可能須要將不少個條件組合在一塊兒查出最後的結果,這個時候就須要使用ES提供的bool
來實現了
例如咱們要查詢host
爲ops-coffee.cn
且http_x_forworded_for
爲111.18.78.128
且status
不爲200的全部數據就可使用下邊的語句
GET /ops-coffee-2019.05.14/_search { "query":{ "bool": { "filter": [ {"match": { "host": "ops-coffee.cn" }}, {"match": { "http_x_forwarded_for": "111.18.78.128" }} ], "must_not": { "match": { "status": 200 } } } } }
主要有四個關鍵字來組合查詢之間的關係,分別爲:
must: 相似於SQL中的AND,必須包含
must_not: 相似於SQL中的NOT,必須不包含
should: 知足這些條件中的任何條件都會增長評分_score
,不知足也不影響,should
只會影響查詢結果的_score
值,並不會影響結果的內容
filter: 與must類似,但不會對結果進行相關性評分_score
,大多數狀況下咱們對於日誌的需求都無相關性的要求,因此建議查詢的過程當中多用filter
ES的查詢博大精深,本篇文章屬於基礎入門,內容來源於官網
網上關於ELK搭建部署日誌收集的文章不少,但收集到日誌以後該如何應用這個數據寶庫呢?網上僅有一些大廠分享的比較泛的概念沒有實際落地的過程,我在想把這些數據利用起來,初步想法是去ES搜索出來業務或者功能的流量數據,而後作趨勢分析,這不從DSL開始學習,歡迎你們加我好友找我交流,我會很是樂意
相關文章推薦閱讀: