開發與維運

大神都這麼做,讓 Kibana 搜索語法 query string 也能輕鬆上手

作者介紹

魏彬,普翔科技 CTO,開源軟件愛好者,中國第一位 Elastic 認證工程師,《Elastic日報》和 《ElasticTalk》社區項目發起人,被 elastic 中國公司授予 2019 年度合作伙伴架構師特別貢獻獎。對 Elasticsearch、Kibana、Beats、Logstash、Grafana 等開源軟件有豐富的實踐經驗,為零售、金融、保險、證券、科技等眾多行業的客戶提供過諮詢和培訓服務,幫助客戶在實際業務中找準開源軟件的定位,實現從 0 到 1 的落地、從 1 到 N 的拓展,產生實際的業務價值。

用過 Kibana 的同學應該都注意過其頂部的搜索框,像下圖這樣。

image.png

這個輸入框接受符合 query string 語法的查詢語句。在日常開發中我們常用的都是 elastic query dsl(domain specific language),都是 json 格式的,像下面這個簡單的查詢語句。

{
    "query":{
        "match":{
            "name":"elastic"
        }
    }
}

這個查詢如果用 query string 來表示的話,如下所示:

ame:elastic

看起來是不是簡潔了很多呢?對於 kibana 這種 UI 界面,輸入越是簡單,越是接近自然語言,對於用戶也就越是友好,所以 kibana 的搜索框默認選擇了 query string 的搜索語法。雖然 query string 展示起來簡潔了很多,但是要用好卻沒有那麼簡單,如果不好好閱讀官方文檔並做實驗,那你會吃不少苦頭。下面我就來幫大家掃清障礙。

註解:如果非要用 query dsl 的話,kibana 也是支持的,你只需要把 query 中的內容放到搜索框中就可以了,比如上面的查詢語句,你只要放下面的內容就可以查詢了。

{    
    "match":{    
        "name":"elastic"
    }
}

由來

Elasticsearch 的 query string 其實就是 lucene 的 query language。elasticsearch 本身就是構建於 lucene 之上的,它支持 lucene 的 query language 也是很簡單的事情。那這個 query language 是怎麼來的呢?根據 lucene 文檔中介紹,雖然 lucene 已經提供了構建查詢條件的 API,但對於人類直接使用而言不夠友好和自然,所以 lucene 提供了這樣一種接近自然語言的查詢語言,方便人工輸入和記憶查詢條件。lucene 不鼓勵在代碼中直接使用 query language,因為它還要經過一層 query parser 的轉換,有性能損耗,另外 query language 也只覆蓋了一部分查詢 API,並不完備。

基本概念

這裡先講解兩個術語: single term 和 phrase。前者是指單個詞(分詞後的最小單位),後者指短語。舉例來說,word、sun 這些都是 single term,而用雙引號包裹起來 “word sun“ 就成了 phrase 。所以這兩者的區別在於 phrase 是由 term 組成的,包裹在雙引號中。而 phrase 中的詞在匹配是有順序要求的,這也就是 elasticsearch 中 match query 和 match phrase query 的區別之一。

這裡先講解兩個術語: single term 和 phrase。前者是指單個詞(分詞後的最小單位),後者指短語。舉例來說,word、sun 這些都是 single term,而用雙引號包裹起來 “word sun“ 就成了 phrase 。所以這兩者的區別在於 phrase 是由 term 組成的,包裹在雙引號中。而 phrase 中的詞在匹配是有順序要求的,這也就是 elasticsearch 中 match query 和 match phrase query 的區別之一。

name:tom

如果不寫 name: ,只寫 tom,那麼相當於執行 _all:tom 這個查詢。

另外 field 是有作用域的,只對緊跟其後的 term 生效。

name:"Tom Lee"

上面這是一個 phrase 查詢,查詢匹配 Tom Lee 的所有文檔。

name:Tom Lee

上面這個查詢實際等效於

name:Tom OR _all:Lee

這也是在實際使用中很多人容易踩坑的地方,使用的過程中要切記,否則查詢出的結果肯定不會如你預期的那樣。

如果你想對一個 field 指定複雜的查詢條件,那麼可以使用括號將查詢條件包起來用(field grouping)。比如下面的這個語句:

name:(tom lee)

等價於

name:(tom OR lee)

查詢 name 為 tom 或者 lee的所有文檔。

另外括號不僅可以作用在 field 上,還可以作用在外層的邏輯處理中。比如下面這種查詢組合也是支持的(大家先忽略還沒有講到的操作符)。

(name:tom && age:10)||city:(shanghai beijing)

有心的讀者可能會發現為什麼 && 的語句還要加括號呢,它的優先級不是比 || 高嗎?我 也是這麼認為的,但動手測試後發現貌似 lucene 沒有實現這個優先級的解析,所以大家使用的時候注意括號的使用。

下面再講一下布爾操作符,大家對這個應該很熟悉了,比如 AND、OR、NOT等。這裡要注意的一點是:query string 中的布爾操作符必須大寫。如果小寫,比如 and、or、not,query解析器會把他們當做普通 term 解析。比如下面這個語句:

name:tom and age:10

上面的查詢實際對應下面的語句:

name:tom OR _all:and OR age:10

愛思考的同學看到上面的解釋應該就有疑問了。

“這個 OR 是從哪裡來的呢?”

這個 OR 是默認的布爾操作符,當多個查詢條件之間沒有指定布爾關係時,就會使用 OR。

另外可以用 && 和 ||* 分別代替 AND 和 OR,使得查詢語句更簡潔易懂。

NOT 就是非操作,簡寫符號為 !。用法如下:

name:(tom NOT lee)

查詢 name 為 tom,但不是 lee 的所有文檔。

除去 AND、OR、NOT ,query string 還支持 + 和 -,分別對應 must 和 must not 的含義。

name:(tom +lee -alfred)

上面的語句查詢 name 中 含有 lee,不含有 alfred,但可能含有 tom 的所有文檔。

大家可以想一下如果用 AND、OR、NOT 來重寫上面的語句是什麼樣子呢?

name:((lee && !alfred) || (tom && lee && !alfred))

你是不是發現 + 和 - 的好處了?

查詢功能

講完基礎概念,我們再來看看 query string 支持的幾個查詢功能。

範圍查詢 range search

數字、日期類型等都是可以指定範圍的,對於這類可以使用範圍查詢,閉區間用[],開區間用{}。舉幾個例子大家一看就明白了。

age:[1 TO 10] 意為 1<=age<=10
age:[1 TO 10} 意為 1<=age<10
age:[1 TO ] 意為 age>=1
age:[* TO 10] 意為 age<=10

日期也是一樣的用法,只要將數字替換為 2017-01-01 即可。

如果你覺得這樣寫太麻煩了,那可以使用簡略寫法,如下:

age:(>=1 && <=10) 或者 age:(+>=1 +<=10)
age:(>=1 && <10) 或者 age:(+>=1 +<10)
age:>=1
age:<=10

通配符查詢 wildcard search

大家對於通配符應該都不陌生,有 ? 和 * 兩個,前者代表一個字符,後者代表0或多個字符。

name:t?m
name:tom*
name:t*m

上面的使用方式都可以,但是不能把 ? 和 * 放在最前面,因為這會導致 elasticsearch 將所有的分詞都比對一遍,效率低下。

通配符查詢的效率很低,也會佔用較多的內存(因為要把所有符合條件的分詞進行比對),建議大家謹慎使用。

正則查詢 regular expressionsearch

正則查詢如同字面意義所講的,支持正則表達式進行匹配。

name:/[mb]oat/

但這裡並不支持所有的正則語法,使用的時候要注意查看官方文檔說明。另外正則查詢的內存壓力也很大,要謹慎使用。

模糊查詢 fuzzy search

所謂模糊查詢是指允許搜索和匹配的詞(term)之間有差異,比如搜索 surprize,可以匹配到surprise。

name:roam~

上面的語句會匹配到 foam 和 roams,波浪號後面可以指定一個 0~2 的浮點值,用以表示模糊度,我在實際使用中用的不多,就不展開來講了。

近似度查詢 proximity search

所謂近似度查詢是指在一個短語(phrase)中,詞(term)與詞之間距離的匹配。

name:"tom lee"~2

匹配時允許 tom 和 lee 之間有 2 個詞的距離,筆者用的也不多,所以不班門弄斧了。

提升查詢權重 boosting term

查詢時如果想改變某個查詢條件的權重,可以使用 ^ 來實現。

name:(tom^4 lee)

上面的查詢表示,當 name 中包含 tom 時,其權重是 lee 的4倍,這就意味著相應得分也會高,排序也會靠前。

特殊字符過濾

uery string 本身已經佔據了一些關鍵字,如下

+ - && || ! ( ) { } [ ] ^ " ~ * ? : \ /

當遇到這些關鍵詞時,需要使用 做轉義,比如如果你要搜索 (1+1):2,那麼查詢條件需要寫成\(1\+1\)\:2

總結

至此,query string就講完了,大家可以去愉快地和 kibana 玩耍了,遇到問題時歡迎和筆者我討論哦~

參考文檔

1、https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html#query-string-syntax

2、https://www.timroes.de/2016/05/29/elasticsearch-kibana-queries-in-depth-tutorial/

3、http://lucene.apache.org/core/6_4_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#package.description

4、http://www.lucenetutorial.com/lucene-query-syntax.html

聲明:本文由原文《Kibana頂部的那個輸入框你知道怎麼用嗎?》作者“魏彬”授權轉載,對未經許可擅自使用者,保留追究其法律責任的權利。


image.png

阿里雲Elastic Stack】100%兼容開源ES,獨有9大能力,提供免費X-pack服務(單節點價值$6000)

相關活動


更多折扣活動,請訪問阿里雲 Elasticsearch 官網

阿里雲 Elasticsearch 商業通用版,1核2G ,SSD 20G首月免費
阿里雲 Logstash 2核4G首月免費


image.png

image.png

Leave a Reply

Your email address will not be published. Required fields are marked *