1. 程式人生 > >elasticsearch(5) 請求體搜尋

elasticsearch(5) 請求體搜尋

上一篇提到的輕量搜尋非常簡單便捷,但是通過請求體查詢可以更充分的利用查詢的強大功能。因為_search api中大部分引數是通過HTTP請求體而非查詢字串來傳遞的。

一 空查詢

對於空查詢來說,最簡單的方式就是傳入一個空的請求體,獲取所有文件(預設返回前10個完整文件內容)

GET 127.0.0.1:9200/_search

{}

你也可以使用from 和 size引數

GET 127.0.0.1:9200/_search
{
      "from":10,
      "size":5
}    

這樣的方式來查詢第11條到15條的文件

  • 大家可能會好奇,這明明是一個GET請求方式,為何可以有請求體。事實上這個RFC文件 
    RFC 7231
    — 一個專門負責處理 HTTP 語義和內容的文件 — 並沒有規定一個帶有請求體的 GET 請求應該如何處理。結果是,一些 HTTP 伺服器允許這樣子,而有一些 — 特別是一些用於快取和代理的伺服器則不允許。

為了避免這樣的情況,ES也支援通過POST請求來進行查詢

POST 127.0.0.1:9200/_search
{
      "from":10,
      "size":5
}    

 

二 查詢結構

查詢表示式(Query DSL)是一種非常靈活又富有表現力的 查詢語言。 Elasticsearch 使用它可以以簡單的 JSON 介面來展現 Lucene 功能的絕大部分。在你的應用中,你應該用它來編寫你的查詢語句。它可以使你的查詢語句更靈活、更精確、易讀和易除錯。

要使用查詢表示式只需要將查詢語句傳遞給query引數

  •  典型的查詢語句結構
{
    QUERY_NAME: {
        ARGUMENT: VALUE,
        ARGUMENT: VALUE,...
    }
}

例如

{
    "query": {
        "match": {
            "like": "sport"
        }
    }
}

查詢like欄位包含sport的文件

 

  • 合併查詢語句

查詢語句就行一個組合塊,這些組合塊可以合併組成更加複雜的查詢邏輯

合併查詢語句裡分為兩種型別

1、葉子語句

即類似上述的match語句,可以被用來查詢一個或多個欄位的文件

2、複合語句

用於合併其他查詢語句,可以通過一個bool語句組合其他語句,例如must匹配、must_not匹配,should匹配,或者filters過濾器

示例

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

找出信件正文包含 business opportunity 的星標郵件,或者在收件箱正文包含business opportunity 的非垃圾郵件

 

三 查詢與過濾

查詢元件的使用可以分為兩種情況,查詢情況和過濾情況,這兩種情況是有區別的

  • 對於過濾情況來說,ES只是簡單的過濾查詢,對於文件是不會進行評分的,即文件要麼匹配,要麼就是不匹配,並沒有介於其中的中間狀態。

這種方式比較適用於確定的判斷,例如created介於2017和2018之間,status等於有效等等

  • 對於查詢情況來說,查詢就有了評分,不但需要判斷文件是否匹配,還需要判斷這個文件匹配的多好。

這種情況比較適用於全文搜尋,因為全文搜尋幾乎沒有完全正確的答案

一般情況下,由於查詢情況需要評分,所以它的效率是沒有過濾情況來的好的。通常使用 查詢(query)語句來進行全文 搜尋或者其它任何需要影響相關性得分的搜尋。除此以外的情況都使用過濾(filters)。

  • 實際上從ES2.0開始,過濾情況已經基本被排除了,因為查詢擁有了不評分的能力。

 

四 查詢方法

  • match_all

match_all查詢簡單的匹配所有文件,在沒有指定查詢方式時,它是預設的查詢,它經常與 filter 結合使用。由於所有文件被認為具有相同的相關性,所以文件的_score都為1

{
    "query": {
        "match_all": {}
    }
}
  • match

無論你在任何欄位上進行的是全文搜尋還是精確查詢,match 查詢是你可用的標準查詢。如果是在全文欄位上match,那麼就會使用正確的分析器取分析查詢字串,如果是在精確值例如整型,時間等,那麼就會精確匹配它。這部分內容會在後面的對映分析部分講到。

{
    "query": {
        "match": {
            "like": "sport"
        }
    }
}
  • multi_match

multi_match查詢可以在多個欄位上執行相同的match, query屬性裡是查詢的條件,fields屬性對應的是多個欄位。

{
    "query": {
        "multi_match": {
            "query": "sport",
            "fields":["like","career"]
        }
    }
}
  • range查詢

range查詢可以找出落在指定區間內的數字或者時間,被允許的操作符有

gt:大於

gte:大於等於

lt:小於

lte:小於等於

{
    "query": {
        "range": {
            "age": {
                "gte": 20,
                "lt": 30
            }
        }
    }
}
  • term查詢

term查詢用於精確值匹配,這些精確值可能是數字、時間、布林或者那些未被分析的字串

 

{ "term": { "age":    26           }}
  • terms查詢

和term一樣,但terms允許指定多值進行匹配,若包含任一值,文件則匹配。匹配的多值通過[ ] 來列出

{ "terms": { "tag": [ "search", "full_text", "nosql" ] }}
  • exists查詢

查詢指定欄位有值,NOT NULL。field:指定欄位

{
    "exists":   {
        "field":    "title"
    }
}
  • missing查詢

和exists相反,查詢指定欄位無值 NULL.

 

五 組合多查詢

可以通過bool查詢來合併組合多查詢,bool查詢接受一下引數

  • must

文件必須匹配這些條件才能被包含

  • must_not

文件必須不匹配這些條件才能被包含

  • should

如果滿足這些語句中的任意語句,將會增加_score,否則無任何影響,它主要用於修正每個文件的相關性得分

  • filter

必須匹配,但它以不評分、過濾模式來進行。這些語句對評分沒有貢獻,只是根據過濾標準來排除或包含文件。所有查詢包括bool查詢本身都可以放置在filter語句中,使其本身不做評分。

 

  • 如果沒有must語句,那麼至少需要能夠匹配其中的一條 should 語句。但,如果存在至少一條 must 語句,則對 should 語句的匹配沒有要求。

 

六 驗證查詢

可以使用_validate/query來驗證查詢是否合法

GET /test/test/_validate/query
{
   "query": {
      "like" : {
         "match" : "sport"
      }
   }
}

響應

{
  "valid" :         false,
  "_shards" : {
    "total" :       10,
    "successful" :  10,
    "failed" :      0
  }
}

這告訴我們這是非法的查詢,這時我們可以使用explain來查詢原因

GET /gb/tweet/_validate/query?explain 
{
   "query": {
      "tweet" : {
         "match" : "really powerful"
      }
   }
}

響應

{
  "valid" :     false,
  "_shards" :   { ... },
  "explanations" : [ {
    "index" :   "gb",
    "valid" :   false,
    "error" :   "org.elasticsearch.index.query.QueryParsingException:
                 [gb] No query registered for [tweet]"
  } ]
}

這告訴我們query中沒有註冊的tweet,應該把match和tweet調換位置