1. 程式人生 > 實用技巧 >ES查詢語法

ES查詢語法

一、Searchtimeout

1、設定:預設沒有timeout,如果設定了timeout,那麼會執行timeout機制。

2、Timeout機制:假設使用者查詢結果有1W條資料,但是需要10″才能查詢完畢

        使用者設定了1″的timeout

        那麼不管當前一共查詢到了多少資料,都會在1″後ES講停止查詢,並返回當前資料。

3、用法:GET /_search?timeout=1s/ms/m

二、Query DSL

1、match_all:匹配所有

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

2、matchname中包含“nfc”

GET /product/_search
{
  "query": {
    "match": {
      "name": "nfc"
    }
  }
}

3、sort:按照價格倒序排序

GET /product/_search
{
  "query": {
    "multi_match": {
      "query": "nfc",
      "fields": ["name","desc"]
    }
  },
  "sort": [
    {
      "price": "
desc" } ] }

4、multi_match:根據多個欄位查詢一個關鍵詞,name和desc中包含“nfc”的doc

GET /product/_search
{
  "query": {
    "multi_match": {
      "query": "nfc",
      "fields": ["name","desc"]
    }
  },
  "sort": [
    {
      "price": "desc"
    }
  ]
}

5、_source 元資料:想要查詢多個欄位,例子中為只查詢“name”和“price”欄位。

GET /product/_search
{
  "query":{
    "match": {
      "name": "nfc"
    }
  },
  "_source": ["name","price"]
}

6、分頁(deep-paging):查詢第一頁(每頁兩條資料)

GET /product/_search
{
  "query":{
    "match_all": {}
  },
  "sort": [
    {
      "price": "asc"
    }
  ],
  "from": 0,
  "size": 2
}

三、Full-text queries

1、query-term:不會被分詞

  (name:nfc phone)中nfc phone不會被分詞,但是doc會被分詞,所以在es中查詢時結果為0

GET /product/_search
{
  "query": {
    "term": {
      "name": "nfc phone"
    }
  }
}
GET /product/_search
{
  "query": {
    "terms": {
      "name":["nfc","phone"]
    }
  }
}

2、match和term的區別:

GET /product/_search
{
  "query": {
    "term": {
      "name": "nfc phone" 這裡因為沒有分詞,所以查詢沒有結果
    }
  }
}

3、全文檢索

GET /product/_search
{
  "query": {
    "match": {
      "name": "xiaomi nfc zhineng phone"
    }
  }
}
#驗證分詞
GET /_analyze
{
  "analyzer": "standard",
  "text":"xiaomi nfc zhineng phone"
}

四、短語搜尋

GET /product/_search
{
  "query": {
    "match_phrase": {
      "name": "nfc phone"
    }
  }
}

五、查詢和過濾

1、bool

  可以組合多個查詢條件,bool查詢也是採用more_matches_is_better的機制,因此滿足must和should子句的文件將會合並起來計算分值。

  ①must:必須滿足

    子句(查詢)必須出現在匹配的文件中,並將有助於得分。

  ②filter:過濾器,不計算相關度分數

    子句(查詢)必須出現在匹配的文件中。但是不像must查詢的分數將被忽略。

    Filter子句在filter上下文中執行,這意味著計分被忽略,並且子句被考慮用於快取。

  ③should:可能滿足 or

    子句(查詢)應出現在匹配的文件中。

  ④must_not:必須不滿足 不計算相關度分數  

    子句(查詢)不得出現在匹配的文件中。子句在過濾器上下文中執行,這意味著計分被忽略

    並且子句被視為用於快取。由於忽略計分,0因此將返回所有文件的分數。

  ⑤minimum_should_match:should配合使用,滿足幾個should條件

  ⑥range:lt大於,gt小於

#首先篩選name包含“xiaomi phone”並且價格大於1999的資料(不排序),

#然後搜尋name包含“xiaomi”and desc 包含“shouji”

GET /product/_search
{
  "query": {
    "bool":{
      "must": [
        {"match": { "name": "xiaomi"}},
        {"match": {"desc": "shouji"}}
      ],
      "filter": [
        {"match_phrase":{"name":"xiaomi phone"}},
        {"range": {
          "price": {
            "gt": 1999
          }
        }}
      ]
    }
  }
}

2、bool多條件

  name包含xiaomi 不包含erji 描述裡包不包含nfc都可以,價錢要大於等於4999

GET /product/_search
{
  "query": {
  "bool":{
    #name中必須不能包含“erji”
      "must": [
        {"match": { "name": "xiaomi"}}
      ],
    #name中必須包含“xiaomi”
      "must_not": [
        {"match": { "name": "erji"}}
      ],
    #should中至少滿足0個條件,參見下面的minimum_should_match的解釋
      "should": [
        {"match": {
          "desc": "nfc"
        }}
      ], 
    #篩選價格大於4999的doc
      "filter": [        
        {"range": {
          "price": {
            "gt": 4999   
          }
        }}
      ]
    }
  }
}

3、巢狀查詢

minimum_should_match:引數指定should返回的文件必須匹配的子句的數量或百分比。如果bool查詢包含至少一個should子句,而沒有must或 filter子句,則預設值為1。否則,預設值為0

GET /product/_search
{
  "query": {
    "bool": {
      "filter": {
        "bool": {
          "should": [
            { "range": {"price": {"gt": 1999}}},
            { "range": {"price": {"gt": 3999}}}
          ],
          "must": [
            { "match": {"name": "nfc"}}
          ]
        }
      }
    }
  }
}

4、組合查詢

搜尋一臺xiaomi nfc phone或者一臺滿足 是一臺手機 並且 價格小於等於2999

GET /product/_search
{
  "query": {
    "constant_score": {
      "filter": { 
        "bool":{
          "should":[
            {"match_phrase":{"name":"xiaomi nfc phone"}},
            {
              "bool":{
                "must":[
                  {"term":{"name":"phone"}},
                  {"range":{"price":{"lte":"2999"}}}
                  ]
              }
            }
          ]
        }
      }
    }
  }
}

5、高亮

GET /product/_search
{
    "query" : {
        "match_phrase" : {
            "name" : "nfc phone"
        }
    },
    "highlight":{
      "fields":{
         "name":{}
      }
    }
}

六、Deep paging問題

使用場景:當你的資料超過1W時,不要使用,返回不要超過1000個

解決辦法:儘量避免深查詢,使用Scroll search

如上圖所示:

  使用者要查詢5001~5050條資料。一個叢集有5個PShard分片構成完整資料,每個PShard中有1W資料

  這時ES會在每個分片中將前5050條資料取出,這時一共會取出25250條資料,十分耗效能