1. 程式人生 > >2.Elasticsearch查詢-請求體查詢、排序

2.Elasticsearch查詢-請求體查詢、排序

spa order 復合 過多 query 布爾邏輯 acc type core

一、請求體查詢

請求體 search API, 之所以稱之為請求體查詢(Full-Body Search),因為大部分參數是通過http請求體而非查詢字符串來傳遞的。
請求體查詢:不僅可以處理自身的查詢請求,還允許你對結果進行片段強調(高亮)、對所有或部分結果進行聚合分析,同時還可以給出 你是不是想找 的建議,這些建議可以引導使用者快速找到他想要的結果。
某些特定語言(特別是 JavaScript)的 HTTP 庫是不允許 GET 請求帶有請求體的,可以用POST代替。

1、空查詢

空查詢,空的請求體會返回所有索引中的所有文檔

GET /_search
{}

用一個查詢字符串,在多個索引庫中和多個types中查詢:

GET /index_2014*/type1,type2/_search
{}

使用 from 和 size 參數分頁:

GET /_search
{
  "from": 30,
  "size": 10
}

2、查詢表達式(Query DSL)

使用

將查詢語句傳遞給query參數

GET /_search
{
    "query": YOUR_QUERY_HERE
}

查詢語句結構

典型結構:

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

針對某個字段:

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

例子:

GET /_search
{
    "query": {
        "match": {
            "city": "Shaft"
        }
    }
}

match_all查詢

空查詢(empty search),在功能上等價於使用 match_all 查詢:

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

合並查詢語句

葉子語句:用於將查詢字符串和一個字段(或者多個字段)對比,match
復合語句:主要用於合並其它查詢語句,bool

GET /_search
{
    "query": {
        "bool": {
            "must":{"match":{"state":"KY"}},
            "must_not":{"match":{"city:":"Yettem"}},
            "should":{"match":{"address":"382 Columbia Street"}},
            "filter":   { "range": { "age" : { "gt" : 30 }} }
          }
    }
}

3、查詢與過濾

過濾
查詢被設置成一個“不評分”或者“過濾”查詢。匹配或者不匹配。
查詢
查詢就變成了一個“評分”的查詢。一個評分查詢計算每一個文檔與此查詢的相關程度,同時將這個相關程度分配給表示相關性的字段_score,並且按照相關性對匹配到的文檔進行排序。
註意
"filter" 這個詞表示不評分、只過濾情況下的查詢。== "filter" 、 "filtering query" 和 "non-scoring query"
"query" 我們指的是 "scoring query"
性能差異
過濾查詢(Filtering queries:計算快,經常用不評分查詢結果稀少,結果會被緩存到內存中以便快速讀取,所以有各種各樣的手段來優化查詢結果。
評分查詢(scoring queries):計算費力,查詢結果並不緩存。

4、最重要的查詢

match_all查詢

匹配所有文檔,默認查詢方式。它經常與 filter 結合使用

{ "match_all": {}}

match查詢

標準查詢,無論你在任何字段上進行的是全文搜索還是精確查詢。
全文字段使用時,在執行查詢前,它將用正確的分析器去分析查詢字符串

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

在一個精確值字段使用,例如數字、日期、布爾或者一個 not_analyzed 字符串字段,它會精確匹配給定的值:

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

multi_match 查詢

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

GET /_search
{
    "query": {
        "multi_match": {
           "query":    "728",
           "fields":   [ "address", "account_number" ]
         }
    }
}

解釋:查詢在address和account_number字段帶有728字符串的文檔。

range查詢

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

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

操作符如下:

  • gt 大於
  • gte 大於等於
  • lt 小於
  • lte 小於等於

term查詢

被用於精確值匹配,這些精確值可能是數字、時間、布爾或者那些 not_analyzed 的字符串:

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

註意:以上某一行

terms查詢

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

GET /_search
{
    "query": {
        "terms": { "age": [39,38,30 ] }
    }
}

解釋:年齡為39或38或30的文檔。

exists查詢、missing查詢

用於查找那些指定字段中有值 (exists) 或無值 (missing) 的文檔:

GET /_search
{
    "query": {
        "exists": {
            "field":    "title"
        }
    }
}

解釋:查詢title字段有值的文檔

5、組合多查詢

可用bool查詢,它接受以下參數:

  • must:文檔 必須 匹配這些條件才能被包含進來。
  • must_not:文檔 必須不 匹配這些條件才能被包含進來。
  • should:如果滿足這些語句中的任意語句,將增加_score ,否則,無任何影響。它們主要用於修正每個文檔的相關性得分。
  • filter:必須 匹配,但它以不評分、過濾模式來進行。這些語句對評分沒有貢獻,只是根據過濾標準來排除或包含文檔。

    bool查詢

    查找 title 字段匹配 how to make millions 並且不被標識為 spam 的文檔。那些被標識為 starred 或在2014之後的文檔,將比另外那些文檔擁有更高的排名。如果_兩者_都滿足,那麽它排名將更高:
{
    "bool": {
        "must":     { "match": { "title": "how to make millions" }},
        "must_not": { "match": { "tag":   "spam" }},
        "should": [
            { "match": { "tag": "starred" }},
            { "range": { "date": { "gte": "2014-01-01" }}}
        ]
    }
}

增加帶過濾器的bool查詢

如果我們不想因為文檔的時間而影響得分,可以用 filter 語句來重寫前面的例子:

{
??? "bool": {
??????? "must":???? { "match": { "title": "how to make millions" }},
??????? "must_not": { "match": { "tag":?? "spam" }},
??????? "should": [
??????????? { "match": { "tag": "starred" }}
??????? ],
??????? "filter": {
????????? "range": { "date": { "gte": "2014-01-01" }} ![0f67842b8cc059137a88288e95115a18.png](evernotecid://20C3AB82-3EA7-481C-B3D2-078868D90727/appyinxiangcom/23631184/ENNote/p10?hash=0f67842b8cc059137a88288e95115a18)
          
??????? }
??? }
}

如果你需要通過多個不同的標準來過濾你的文檔,bool查詢本身也可以被用做不評分的查詢,簡單地將它放置到filter語句中並在內部構建布爾邏輯:

{
??? "bool": {
??????? "must":???? { "match": { "title": "how to make millions" }},
??????? "must_not": { "match": { "tag":?? "spam" }},
??????? "should": [
??????????? { "match": { "tag": "starred" }}
??????? ],
??????? "filter": {
????????? "bool": { ![0f67842b8cc059137a88288e95115a18.png](evernotecid://20C3AB82-3EA7-481C-B3D2-078868D90727/appyinxiangcom/23631184/ENNote/p10?hash=0f67842b8cc059137a88288e95115a18)
          
????????????? "must": [
????????????????? { "range": { "date": { "gte": "2014-01-01" }}},
????????????????? { "range": { "price": { "lte": 29.99 }}}
????????????? ],
????????????? "must_not": [
????????????????? { "term": { "category": "ebooks" }}
????????????? ]
????????? }
??????? }
??? }
}

constant_score查詢

可以使用它來取代只有 filter 語句的 bool 查詢,性能相同,但是簡潔:

{
??? "constant_score":?? {
??????? "filter": {
??????????? "term": { "category": "ebooks" } ![0f67842b8cc059137a88288e95115a18.png](evernotecid://20C3AB82-3EA7-481C-B3D2-078868D90727/appyinxiangcom/23631184/ENNote/p10?hash=0f67842b8cc059137a88288e95115a18)
            
??????? }
??? }
}

解釋:term 查詢被放置在 constant_score 中,轉成不評分的 filter。這種方式可以用來取代只有 filter 語句的 bool 查詢。

6、驗證查詢

validate-query API 可以用來驗證查詢是否合法:

GET /bank/address/_validate/query?
{
   "query": {
      "address" : {
         "match" : "Avenue"
      }
   }
}

解釋不合法原因:

GET /bank/address/_validate/query?explain
{
   "query": {
      "address" : {
         "match" : "Avenue"
      }
   }
}

二、排序與相關性

1、排序

在 Elasticsearch 中, 相關性得分 由一個浮點數進行表示,並在搜索結果中通過_score 參數返回, 默認排序是_score 降序。

使用 constant_score 查詢進行替代bool,讓所有文檔應用一個恒定分數(默認為 1 ),不是0:

GET /_search
{
    "query" : {
        "constant_score" : {
            "filter" : {
                "term" : {
                    "user_id" : 1
                }
            }
        }
    }
}

2、按照字段的值排序

GET /_search
{
    "query" : {
        "bool" : {
            "filter" : { "term" : { "age" : 40 }}
        }
    },
    "sort": { "balance": { "order": "desc" }}
}

3、多級排序

假定我們想要結合使用 date和_score 進行查詢,並且匹配的結果首先按照日期排序,然後按照相關性排序:

GET /_search
{
    "query" : {
        "bool" : {
            "must":   { "match": { "tweet": "manage text search" }},
            "filter" : { "term" : { "user_id" : 2 }}
        }
    },
    "sort": [
        { "date":   { "order": "desc" }},
        { "_score": { "order": "desc" }}
    ]
}

Query-string 搜索 也支持自定義排序,可以在查詢字符串中使用 sort 參數:

GET /_search?sort=date:desc&sort=_score&q=search

4、多值字段排序

情形:一個字段裏有多個值,並且這些值沒有順序,應該選擇哪個值排序。
對於數字或日期,你可以將多值字段減為單值,這可以通過使用 min 、 max 、 avg 或是 sum 排序模式 。 例如你可以按照每個 date 字段中的最早日期進行排序,通過以下方法:

"sort": {
    "dates": {
        "order": "asc",
        "mode":  "min"
    }
}

5、字符串排序與多字段

一個簡單的方法是用兩種方式對同一個字符串進行索引,這將在文檔中包括兩個字段: analyzed 用於搜索, not_analyzed 用於排序。

為一個多字段映射如:

"tweet": { ![0f67842b8cc059137a88288e95115a18.png](evernotecid://20C3AB82-3EA7-481C-B3D2-078868D90727/appyinxiangcom/23631184/ENNote/p10?hash=0f67842b8cc059137a88288e95115a18)

??? "type":???? "string",
??? "analyzer": "english",
??? "fields": {
??????? "raw": {        
??????????? "type":? "string",
??????????? "index": "not_analyzed"
??????? }
??? }
}
  • tweet?主字段與之前的一樣: 是一個?analyzed?全文字段。
  • 新的?tweet.raw?子字段是?not_analyzed.

現在,使用 tweet 字段用於搜索,tweet.raw 字段用於排序:

GET /_search
{
    "query": {
        "match": {
            "tweet": "elasticsearch"
        }
    },
    "sort": "tweet.raw"
}

註意:以全文 analyzed 字段排序會消耗大量的內存

2.Elasticsearch查詢-請求體查詢、排序