天天看點

Elasticsearch(入門篇)——Query DSL與查詢行為

ES提供了豐富多彩的查詢接口,可以滿足各種各樣的查詢要求。更多内容請參考:ELK修煉之道

Query DSL結構化查詢

  • Query DSL是一個Java開源架構用于建構類型安全的SQL查詢語句。采用API代替傳統的拼接字元串來構造查詢語句。目前Querydsl支援的平台包括JPA,JDO,SQL,Java Collections,RDF,Lucene,Hibernate Search。
  • elasticsearch提供了一整套基于JSON的查詢DSL語言來定義查詢。
  • Query DSL當作是一系列的抽象的查詢表達式樹(AST)特定查詢能夠包含其它的查詢,(如 bool ), 有些查詢能夠包含過濾器(如 constant_score), 還有的可以同時包含查詢和過濾器 (如 filtered). 都能夠從ES支援查詢集合裡面選擇任意一個查詢或者是從過濾器集合裡面挑選出任意一個過濾器, 這樣的話,我們就可以構造出任意複雜(maybe 非常有趣)的查詢了,是不是很靈活啊。

舉個例子

GET _search
{
    "query": {
        "bool": {
            "must": [
                { "match": { "title": "Search" }},
                { "match": { "content": "Elasticsearch" }}
            ],
            "filter": [
                { "term": { "status": "published" }},
                { "range": { "publish_date": { "gte": "2015­01­01" }}}
            ]
        }
    }
}           

複制

查詢的分類

Leaf query Cluase 葉子查詢(簡單查詢)

這種查詢可以單獨使用,針對指定的字段查詢指定的值。

Compound query clauses 複雜查詢

複雜查詢可以包含葉子或者其它的複雜查詢語句,用于組合成複雜的查詢語句,比如not, bool等。

查詢雖然包含這兩種,但是查詢的行為還與查詢的執行環境有關,不同的執行環境,查詢操作也不一樣。

查詢的行為取決于他們所在的查詢上下文,包括Query查詢上下文和Filter查詢上下文。

查詢與過濾

  • Query查詢上下文

    在Query查詢上下文中,查詢會回答這個問題--"這個文檔匹不比對查詢條件,它的相關性高麼?"

    除了決定文檔是夠比對,針對比對的文檔,查詢語句還會計算一個

    _score

    相關性分值,分數越高,比對度越高,預設傳回是越靠前。這裡關于分值的計算不再介紹,以後再做介紹。
  • Filter過濾器上下文

    在Filter過濾器上下文中,查詢會回答這個問題--"這個文檔是否比對"

    這個結果要麼“不是”要麼“是”,不會計算分值問題,也不會關心傳回的排序問題,這樣性能方面就比Query查詢高了。Filter過濾器主要用于過濾結構化資料,例如:

    • 時間戳範圍是否在2015-2016之間?
    • status字段是否被設定成"published"?

      另外,常用的過濾器會自動緩存Elasticsearch,加速性能。

舉個簡單的例子:

  1. title字段包含關鍵詞"search"
  2. content字段包含關鍵詞"elasticsearch"
  3. status字段存在精确詞"published"
  4. publish_date字段包含一個日期由2015年1月1日起

    GET _search { "query": { "bool": { "must": [ { "match": { "title": "Search" }}, { "match": { "content": "Elasticsearch" }} ], "filter": [ { "term": { "status": "published" }}, { "range": { "publish_date": { "gte": "2015-01-01" }}} ] } } }

性能差異

使用過濾語句得到的結果集———一個簡單的文檔清單,快速比對運算并存入記憶體是非常友善的,每個文檔僅需1個位元組。這些緩存的過濾結果集與後續請求的結合使用時非常高效的。

查詢語句不僅要查找相比對的文檔,還需要計算每個文檔的相關性,是以一般來說查詢語句要比過濾語句更耗時,并且查詢結果也不可緩存。

幸虧有了反向索引,一個隻比對少量文檔的簡單查詢語句在百萬級文檔中的查詢效率會與一條經過緩存的過濾語句旗鼓相當,甚至略占上風。但是一般情況下,一條經過緩存的過濾查詢要遠勝一條查詢語句的執行效率。

總結

  1. Query查詢上下文中,查詢操作會根據查詢的結果進行相關性分值計算,用于确定相關性。分值越高,傳回的結果越靠前。
  2. Filter過濾器上下文中,查詢不會計算相關性分值,也不會對結果進行排序。
  3. 過濾器上下文中,查詢的結果可以被緩存。
  4. 以後部落格中提到的查詢就是在Query查詢上下文,過濾就是指filter過濾器上下文。

  5. 原則上來說,使用查詢語句做全文本搜尋或其他需要進行相關性評分的時候,剩下的全部用過濾語句

參考

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-filter-context.html