Elasticsearch查詢及聚合類DSL語句寶典

京東雲開發者發表於2022-12-27

作者:京東科技 紀海雨

前言

隨著使用es場景的增多,工作當中避免不了去使用es進行資料的儲存,在資料儲存到es當中以後就需要使用DSL語句進行資料的查詢、聚合等操作,DSL對SE的意義就像SQL對MySQL一樣,學會如何編寫查詢語句決定了後期是否能完全駕馭ES,所以至關重要,本專題主要是分享常用的DSL語句,拿來即用。

一、match

如果match 查詢數字,日期,布林值或者not_analyzed 的字串時,會精確匹配搜尋值,不做分詞解析;如果match 查詢全文字,會對查詢詞做分詞解析,然後搜尋。

比如對keyword 型別的tag 查詢,"京東總部"不會分詞,必須完全相等的詞才會被搜尋出來

{a
  "query": {
    "match": {
        "content" : {
            "tag" : "京東總部"
        }
    }
  }
}

比如"寶馬多少馬力"會被分詞為"寶馬 多少 馬力", 所有有關"寶馬 多少 馬力", 那麼所有包含這三個詞中的一個或多個的文件就會被搜尋出來。並且根據lucene的評分機制(TF/IDF)來進行評分

{
  "query": {
    "match": {
        "content" : {
            "query" : "寶馬多少馬力"
        }
    }
  }
}

二、match_phrase

如果想要精確匹配所有同時包含"寶馬 多少 馬力"的文件,就要使用 match_phrase 了

{
  "query": {
    "match_phrase": {
        "content" : {
            "query" : "寶馬多少馬力"
        }
    }
  }
}

三、mult_match

如果我們希望兩個欄位進行匹配,其中一個欄位有這個文件就滿足的話,使用multi_match

{
  "query": {
    "multi_match": {
        "query" : "我的寶馬多少馬力",
        "fields" : ["title", "content"]
    }
  }
}

四、term

關鍵字精確匹配,不分詞解析。注意 term 包含(contains) 操作,而非 等值(equals)判斷。如果文件包含full_text 及其他詞,也會命中返回。

使用term要確定的是這個欄位是否“被分析”(analyzed),預設的字串是被分析的。

比如下面的例子,其中的full_text是被分析過的,所以full_text的索引中存的就是[quick, foxes],而extra_value中存的是[Quick Foxes!]

PUT my_index
{
  "mappings": {
    "my_type": {
      "properties": {
        "full_text": {
          "type":  "string"
        },
        "exact_value": {
          "type":  "string",
          "index": "not_analyzed"
        }
      }
    }
  }
}

PUT my_index/my_type/1
{
  "full_text":   "Quick Foxes!",
  "exact_value": "Quick Foxes!"  
}

請求不出資料的,因為full_text分詞後的結果中沒有[Quick Foxes!]這個分詞

GET my_index/my_type/_search
{
  "query": {
    "term": {
      "full_text": "Quick Foxes!"
    }
  }
}

五、terms

指定多值精確匹配,如果欄位包含了指定值中的任何一個值,那麼文件滿足條件。類似sql中的in

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

六、range

數字/時間的區間查詢,運算子:

gt > greater than

gte >=

lt < litter than

lte <=

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

七、wildcard

萬用字元索引。* 表示全匹配,? 表示單一匹配。掃描所有倒排索引,效能較差

{ 
  "query": { 
    "wildcard": { 
      "companyName": "*京東*" 
    } 
  } 
}

八、regexp

正則索引。掃描所有倒排索引,效能較差

{ 
    "query": { 
        "regexp": { 
            "postcode": "W[0-9].+" 
        } 
    } 
}

九、組合多查詢(bool查詢)

bool 查詢後面可以跟這四種匹配模式

•must 必須匹配

•must_not 必須不匹配

•should 匹配任意,等價or

•filter 必須匹配:過濾模式

比如我們想要請求"content 中帶寶馬,但是tag 中不帶寶馬"這樣類似的需求,就需要用到bool 聯合查詢。

{
    "query":{
        "bool":{
            "must":{
                "term":{
                    "content":"寶馬"
                }
            },
            "must_not":{
                "term":{
                    "tags":"寶馬"
                }
            }
        }
    }
}

十、聚合

聚合包含一下兩種:

1、 指標聚合(Metric Aggregation):一些數學運算,可以對文件欄位進行統計分析

•輸出一個值

▪min

▪max

▪sum

▪avg

▪ value_count 統計某欄位有值的文件數

▪ cardinality 某欄位值去重計數

•輸出多個值

▪stats

▪percentiles

▪percentile_ranks

2、桶聚合(Bucket Aggregation) :一些列滿足特定條件的文件的集合,相當於sql 的groupby

•terms 對某個欄位統計每個不同的內容,以及出現文件的個數

•range 某個範圍內文件的個數

預設聚合範圍是全文,但是如果有query查詢,那麼聚合的範圍就是query查詢的結果。

value_count 統計某欄位有值的文件數

{
  "size": 0, 
  "aggs": {
    "count": {
      "value_count": {
        "field": "companyName"
      }
    }
  }
}

指定查詢語句進行統計

{
  "query": {
    "term": {
      "companyName": "安徽科達智慧能源科技有限公司"
    }
  },
  "aggs": {
    "count": {   //自定義名稱
      "terms": {
        "field": "companyName"
      }
    }
  }
}



以上就是本期分享的DSL語句,小夥伴們結合自己的使用查詢場景進行操練起來吧。

相關文章