天天看點

Elasticsearch學習系列之常用查詢表達式Query DSL

Elasticsearch查詢模式

一種是像傳遞URL參數一樣去傳遞查詢語句,被稱為簡單查詢

GET /library/books/_search //查詢index為library,type為books的全部内容
GET /library/books/_search?q=price:10 //查詢index為library,type為books中price等于10的
           

另一種是DSL語句來進行查詢,被稱為DSL查詢,term和match就屬于DSL

查詢表達式

查詢表達式(Query DSL)是一種非常靈活又富有表現力的查詢語言。Elasticsearch 使用它可以以簡單的

JSON接口來展現Luncene功能的絕大部分。在你的應用中,你應該用它來編寫你的查詢語句。它可以使你的

查詢語句更靈活、更精确、易讀和易調試。

要使用這種查詢表達式,隻需要将查詢語句傳遞給query參數:

GET /_search
{
    "query": YOUR_QUERY_HERE
}
           

空查詢(empty search)-{}-在功能上等價于使用match_all查詢,正如其名字一樣,比對所有文檔:

GET /_search
{
    "query": {
        "match_all": {}
    }
}
           

查詢語句的結構

一個查詢語句的典型結構:

{
    QUERY_NAME: {
        ARGUMENT: VALUE,
        ARGUMENT: VALUE,...
    }
}
           

如果是針對某個字段,那麼它的結構如下:

{
    QUERY_NAME: {
        FIELD_NAME: {
            ARGUMENT: VALUE,
            ARGUMENT: VALUE,...
        }
    }
}
           

舉個例子,你可以使用match查詢語句來查詢tweet字段中包含 

elasticsearch

 的 tweet:

{
    "match": {
        "tweet": "elasticsearch"
    }
}
           

完整的查詢請求如下:

GET /_search
{
    "query": {
        "match": {
            "tweet": "elasticsearch"
        }
    }
}
           

合并查詢語句

查詢語句(Query clauses) 就像一些簡單的組合塊,這些組合塊可以彼此之間合并組成更複雜的查詢。這些語句可以是如下形式:

  • 葉子語句(Leaf clauses) (就像 

    match

     語句) 被用于将查詢字元串和一個字段(或者多個字段)對比。
  • 複合(Compound) 語句 主要用于 合并其它查詢語句。 比如,一個 

    bool

     語句 允許在你需要的時候組合其它語句,無論是 

    must

     比對、 

    must_not

     比對還是 

    should

     比對,同時它可以包含不評分的過濾器(filters):
    {
        "bool": {
            "must":     { "match": { "tweet": "elasticsearch" }},
            "must_not": { "match": { "name":  "mary" }},
            "should":   { "match": { "tweet": "full text" }},
            "filter":   { "range": { "age" : { "gt" : 30 }} }  --包含不含評分的過濾器
        }
    }
               

一條複合語句可以合并 任何 其它查詢語句,包括複合語句,了解這一點是很重要的。這就意味着,複合語句之間可以互相嵌套,可以表達非常複雜的邏輯。

例如,以下查詢是為了找出信件正文包含 

business opportunity

 的星标郵件,或者在收件箱正文包含 

business opportunity

 的非垃圾郵件:

{
    "bool": {
        "must": { "match":   { "email": "business opportunity" }},
        "should": [
            { "match":       { "starred": true }},
            { "bool": {
                "must":      { "match": { "folder": "inbox" }},
                "must_not":  { "match": { "spam": true }}
            }}
        ],
        "minimum_should_match": 1
    }
}
           

查詢與過濾

(了解查詢和上上個例子中filter)

Elasticsearch 使用的查詢語言(DSL)擁有一套查詢元件,這些元件可以以無限組合的方式進行搭配。這套元件可以在以下兩種情況下使用:過濾情況(filtering context)和查詢情況(query context)。

當使用于 過濾情況  時,查詢被設定成一個“不評分”或者“過濾”查詢。即,這個查詢隻是簡單的問一個問題:“這篇文檔是否比對?”。回答也是非常的簡單,yes 或者 no ,二者必居其一。

  • created

     時間是否在 

    2013

     與 

    2014

     這個區間?
  • status

     字段是否包含 

    published

     這個單詞?
  • lat_lon

     字段表示的位置是否在指定點的 

    10km

     範圍内?

當使用于 查詢情況  時,查詢就變成了一個“評分”的查詢。和不評分的查詢類似,也要去判斷這個文檔是否比對,同時它還需要判斷這個文檔比對的有 多好(比對程度如何)。 此查詢的典型用法是用于查找以下文檔:

  • 查找與 

    full text search

     這個詞語最佳比對的文檔
  • 包含 

    run

     這個詞,也能比對 

    runs

     、 

    running

     、 

    jog

     或者 

    sprint

  • 包含 

    quick

     、 

    brown

     和 

    fox

     這幾個詞 — 詞之間離的越近,文檔相關性越高
  • 标有 

    lucene

     、 

    search

     或者 

    java

     标簽 — 标簽越多,相關性越高

一個評分查詢計算每一個文檔與此查詢的 相關程度,同時将這個相關程度配置設定給表示相關性的字段 

_score

,并且按照相關性對比對到的文檔進行排序。這種相關性的概念是非常适合全文搜尋的情況,因為全文搜尋幾乎沒有完全 “正确” 的答案。

最重要的查詢

雖然 Elasticsearch 自帶了很多的查詢,但經常用到的也就那麼幾個,我們對最重要的幾個查詢進行簡單介紹

term查詢

term是代表完全比對,即不進行分詞器分析,文檔中必須包含整個搜尋的詞彙

term查詢對于輸入的文本不分析,是以它将給定的值進行精确查詢。

格式

GET /library/books/_search       #這裡是變化的,指定index和type;(比如說index為library,type為books)
{
  "query": {
    "term": {
        "key": "value"              #這裡是變化的,比如說查詢title等于elasticsearch的内容
      }
    }
}
           

執行個體1:查詢index為library,type為books重title等于elasticsearch的内容

GET /library/books/_search
{
  "query": {
    "term": {
        "title": "elasticsearch"
    }
  }
}
           

term查詢被用于精确值比對,這些精确值可能是數字、時間、布爾或者那些not_analyzed的字元串:

{ "term": { "age":    26           }}
{ "term": { "date":   "2014-09-01" }}
{ "term": { "public": true         }}
{ "term": { "tag":    "full_text"  }}
           

terms查詢

terms

 查詢和 

term

 查詢一樣,但它允許你指定多值進行比對。如果這個字段包含了指定值中的任何一個值,那麼這個文檔滿足條件:

{ "terms": { "tag": [ "search", "full_text", "nosql" ] }}
           

和 

term

 查詢一樣,

terms

 查詢對于輸入的文本不分析。它查詢那些精确比對的值(包括在大小寫、重音、空格等方面的差異)

match查詢

match和term的差別是,match查詢的時候,elasticsearch會根據你給定的字段提供合适的分析器,而term查詢不會有分析器分析的過程

match查詢相當于模糊比對,隻包含其中一部分關鍵詞就行

如果用match下指定了一個确切值,在遇到數字,日期,布爾值或者not_analyzed 的字元串時,它将為你搜尋你給定的值。

補充:個人感覺match查詢相當于模糊比對,隻包含其中一部分關鍵詞就行,這句話又誤,match應該也是精确查詢,與term的差別是 term不會有分析器分析的過程。如果想要模糊查詢的話,還是用wildcard加通配符。

格式

GET /library/books/_search 
{
    "query":{
        "match":{
            "key":"value"      
        }
    }
}
           

執行個體1:過濾出preview字段中包含"elasticsearch"的索引,并且隻顯示preview和title字段

GET /library/books/_search 
{
    "fields":["preview","title"]
    "query":{
        "match":{
            "preview":"elasticsearch"      
        }
    }
}
           

如果你在一個全文字段上使用 

match

 查詢,在執行查詢前,它将用正确的分析器去分析查詢字元串:

{ "match": { "tweet": "About Search" }}
           

如果在一個精确值的字段上使用它,例如數字、日期、布爾或者一個 

not_analyzed

 字元串字段,那麼它将會精确比對給定的值:

{ "match": { "age":    26           }}
{ "match": { "date":   "2014-09-01" }}
{ "match": { "public": true         }}
{ "match": { "tag":    "full_text"  }}
           

match_all查詢

查詢指定索引下的所有文檔

執行個體1:過濾出index為library,type為books的所有文檔

GET /library/books/_search 
{
    "query":{
        "match_all":{}   
        }                                    
}
           

執行個體2:通過match_all過濾出所有字段,然後通過partial在過濾出包含preview的字段和排除title,price的字段

GET /library/books/_search 
{
    "partial_fields":{
        "partial":{
            "include":["preview"],         #包含preview字段的文檔
            "exclude":["title,price"]    #排除title,price字段
        },
    "query":{
        "match_all":[]
    }
    }
}
           

match_phrase查詢

短語查詢,slop定義的是關鍵詞之間隔多少未知單詞

格式

GET /library/books/_search 
{
    "query":{
        "match_phrase" :{
            "query":"Elasticsearch,distributed",
            "slop":2                                 #表示Elasticsearch和distributed之間隔多少單詞
        }
    }
}
           

multi_match查詢

可以指定多個字段

執行個體1:查詢title和preview這兩個字段都包含Elasticsearch關鍵詞的文檔

GET /library/books/_search 
{
    "query":{
        "multi_match":{
            "query":"Elasticsearch"
            "fields":["title","preview"]
        }
    }
}
           

multi_match

 查詢可以在多個字段上執行相同的 

match

 查詢:

{
    "multi_match": {
        "query":    "full text search",
        "fields":   [ "title", "body" ]
    }
}
           

range

 查詢找出那些落在指定區間内的數字或者時間:

{
    "range": {
        "age": {
            "gte":  20,
            "lt":   30
        }
    }
}
           

被允許的操作符如下:

gt

大于

gte

大于等于

lt

小于

lte

小于等于

exists 查詢和 missing 查詢

exists

 查詢和 

missing

 查詢被用于查找那些指定字段中有值 (

exists

) 或無值 (

missing

) 的文檔。這與SQL中的 

IS_NULL

 (

missing

) 和 

NOT IS_NULL

 (

exists

) 在本質上具有共性:

{
    "exists":   {
        "field":    "title"
    }
}
           

filter過濾查詢

查詢同時,通過filter條件在不影響打分的情況下篩選出想要的資料

簡單的filter查詢

執行個體1:先查詢index為store,type為products的全部文檔;再過濾price等于20的

GET /store/products/_search
{
  "query": {
    "filtered":{
        "query":{
            "match_all": {}  #先查詢index為store,type
        },
        "filter": {
          "term" :{
              "price":20    #這裡是條件,price等于20的
          }
        }
    }
  }
}
           

filter之bool過濾查詢

格式

{
"bool":{
    "must"        : [],
    "should"   : [],
    "must_not" : [],
}
}
#must:條件必須滿足,相當于sql語句的and
#should:條件可以滿足也可以不滿足,相當于sql語句的or
#must_not:條件不需要滿足,相當于sql語句的not
           

執行個體1:查詢價格等于20或者productID等于SD1002136的商品,再排除價格等于30的

GET /store/products/_search
{
  "query": {
    "filtered":{
      "filter":{
        "bool":{
          "should": [
            {"term" : {"price" : 20}},
            {"term" : {"productID" : "SD1002136"}}
          ],
          "must_not": {
            "term" :{"price":30}
          }
        }
      
    }
  }
}
}
           

filter之and,not,or查詢

沒有bool,也可以直接使用and,or,not

執行個體1:and用法,查詢價格是10元并且productID又是SD1002136的結果

GET /store/products/_search
{
  "query":{
    "filtered":{
      "filter":{
        "and":[
          {
            "term":{
              "price":10
            }
          },
          {
            "term":{
              "productID":"SD1002136"
            }
          }
          ]
      },
      "query":{
        "match_all": {}
      }
    }
  }
  
}
           

執行個體2:or用法,查詢價格是10元或者productID是SD4535233的商品

GET /store/products/_search
{
  "query":{
    "filtered":{
      "filter":{
        "or":[
          {
            "term":{
              "price":10
            }
          },
          {
            "term":{
              "productID":"SD4535233"
            }
          }
          ]
      },
      "query":{
        "match_all":{}
      }
    }
  }
}
           

執行個體3:not用法,查詢productID不是SD1002136的商品

GET /store/products/_search
{
  "query":{
    "filtered":{
      "filter":{
        "not":{
          "term":{
            "productID":"SD1002136"
          }
        }
      },
      "query":{
        "match_all": {}
      }
    }
  }
}
           

filter之range範圍查詢

格式

GET /store/products/_search
{
    "query":{
        "filtered":{
            "filter":{
                "range":{
                    "key":{
                        "條件" : value1
                        "條件": value2
                    }
                }
            }
        }
    }
}
           

條件

gt : 大于
lt : 小于
gte : 大于等于
lte :小于等于
           

執行個體1:查詢price大于等于20小于等于40的結果

GET /store/products/_search
{
    "query":{
        "filtered":{
            "filter":{
                "range":{
                    "price":{
                        "gte" : 20,
                        "lte" : 40
                    }
                }
            }
        }
    }
}
           

轉載于:https://www.cnblogs.com/zhaijunming5/p/6427100.html

https://www.elastic.co/guide/cn/elasticsearch/guide/current/_most_important_queries.html#_exists_%E6%9F%A5%E8%AF%A2%E5%92%8C_missing_%E6%9F%A5%E8%AF%A2

繼續閱讀