ES 復合查詢


  ES在查詢過程中比較多遇到符合查詢,既需要多個字段過濾也需要特殊情況處理,本文簡單介紹幾種查詢組合方便快捷查詢ES。

bool(組合查詢)

  1. must 所有的語句都 必須(must) 匹配,與 AND 、= 等價。
  2. must_not 所有的語句都 不能(must not) 匹配,與 NOT 、!= 等價。
  3. should 至少有一個語句要匹配,與 OR 等價。
   
filter 只過濾符合條件的文檔,不計算相關系得分
must 文檔必須符合must中所有的條件,會影響相關性得分
must_not 文檔必須不符合must_not 中的所有條件
should 文檔可以符合should中的條件

 

 

 

 

 

 

它類似於SQL中的WHERE A = 'a' AND B = 'c' OR C = 'c'。一個 bool 過濾器由三部分組成:

{
   "bool" : {
      "must" :     [],
      "should" :   [],
      "must_not" : [],
   }
}

 

布爾查詢是一種最常用的組合查詢方式,布爾查詢把多個子查詢組合(combine)成一個布爾表達式,所有子查詢之間的邏輯關系是與(and);只有當一個文檔滿足布爾查詢中的所有子查詢條件時,ElasticSearch引擎才認為該文檔滿足查詢條件。布爾查詢支持的子查詢類型共有四種,分別是:must,should,must_not和filter:

查詢字句 說明 類型
must 文檔必須匹配must查詢條件 數組
should 文檔應該匹配should子句查詢的一個或多個 數組
must_not 文檔不能匹配該查詢條件 數組
filter 過濾器,文檔必須匹配該過濾條件,跟must子句的唯一區別是,filter不影響查詢的score 字典



 
 
 
 
 
 

filter查詢

  • filter查詢只過濾符合條件的文檔,es會有只能緩存,因此其執行效率很高,做簡單的匹配查詢且不考慮算分是,推薦使用filter替代query
上下文類型 執行類型 使用方式
Query 查找和查詢語句最匹配的文檔,對所有文檔進行相關性算分排序 query查詢 bool中的must和should
Filter 查找和查詢語句匹配的文檔 bool中的filter和must_not或者constant_score中的filter

 

 

 

 

should查詢

使用分兩種情況

bool查詢包含should,不包含must查詢,只包含should,文檔必須滿足至少一個條件,minimum_should_match可以滿足條件的個數或者百分比。
bool查詢同時包含should和must查詢,文檔不必滿足should中的條件,但是如果滿足條件,會增加相關性得分(dis_max query/function_score query
/boosting query)。

filter執行原理深度剖析

1.在倒排索引中查找搜索串,獲取document list。
2.為每個在倒排索引中搜索到的結果,構建一個bitset,[0, 0, 0, 1, 0, 1]
3.遍歷每個過濾條件對應的bitset,優先從最稀疏的開始搜索,查找滿足所有條件的document
4.caching bitset,跟蹤query,在最近256個query中超過一定次數的過濾條件,緩存其bitset。對於小segment(<1000,或<3%),不緩存bitset。
5.filter大部分情況下來說,在query之前執行,先盡量過濾掉盡可能多的數據
6.如果document有新增或修改,那么cached bitset會被自動更新
7.以后只要是有相同的filter條件的,會直接來使用這個過濾條件對應的cached bitset

 
實例說明:
1.或者並且查詢
sql:
select
* from paper where (date="2018-10-11" or uID= 1) and pID!="7ec0e0e5-a4b0-46d7-af56-5b3eab477aea" es: GET blog/paper/_search { "query": { "bool": { "should": [ {"term": {"date":"2018-10-11"}}, {"term": {"uID":1}} ] , "must_not": [ {"term": {"pID": "7ec0e0e5-a4b0-46d7-af56-5b3eab477aea"}} ] } } }

2.並且或者查詢

select *from paper where date= "2018-10-11" or(uid=1 and publish= 1)

GET blog/paper/_search
{
  "query": {
    "bool": {
      "should": [
        {"term": {"date": "2018-10-11"}},
        {"bool": {
          "must": [
            {"term": {"uID": "1"}},
            {"term": {"publish": true}}
          ]
        }}
      ]
    }
  }
}

3.搜索java,elasticsearch,hadoop,spark關鍵字需要至少匹配2個

GET blog/paper/_search
{
  "query": {
    "bool": {
      "should": [
        {"match": {
          "title": "java"
        }},
         {"match": {
          "title": "elasticsearch"
        }},
         {"match": {
          "title": "hadoop"
        }},
         {"match": {
          "title": "spark"
        }}
      ]
      , "minimum_should_match": 2
    }
  }
}

 

range(范圍查詢)

我們可以用它來查找處於某個范圍內的文檔。比如我們在商品中查找價格大於 $20 且小於 $40 美元的。

GET /index/type/_search
{
  "query": {
    "range": {
      "price": {
        "gte": 20,
        "lte": 40
      }
    }
  }
}

 

range 查詢可同時提供包含(inclusive)和不包含(exclusive)這兩種范圍表達式,可供組合的選項如下:

  • gt: > 大於(greater than)
  • lt: < 小於(less than)
  • gte: >= 大於或等於(greater than or equal to)
  • lte: <= 小於或等於(less than or equal to)。

range 還可以支持日期范圍, 字符串范圍類型,特別是在進行日期范圍查詢時,range還可以支持日期計算。
像這樣:

"range" : {
    "timestamp" : {
        "gt" : "now-1h"
    }
}

OR

"range" : {
    "timestamp" : {
        "gt" : "2014-01-01",
        "lt" : "2014-01-01||+1y"
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM