ElasticSearch進階檢索

SpringBreeze發表於2021-08-11

ElasticSearch進階檢索

入門檢索中講了如何匯入elastic提供的樣本測試資料,下面我們用這些資料進一步檢索

一、SearchAPI

ES 支援兩種基本方式檢索 :

1、一種是通過使用 REST request URI 傳送搜尋引數(uri+檢索引數)

​ GET bank/_search 檢索 bank 下所有資訊,包括 type 和 docs

​ GET bank/_search?q=*&sort=account_number:asc 請求引數方式檢索

2、另一種是通過使用 REST request body 來傳送它們(uri+請求體)

GET /bank/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "account_number": "asc"
    }
  ]
}
# query 查詢條件
# sort 排序條件

響應結果

響應結果

響應結果解釋:

took - 執行搜尋的時間(毫秒)

time_out - 告訴我們搜尋是否超時

_shards - 告訴我們多少個分片被搜尋了,以及統計了成功/失敗的搜尋分片

hits - 搜尋結果

hits.total - 搜尋結果條數

hits.hits - 實際的搜尋結果陣列(預設為前 10 的文件)

sort - 結果的排序 key(鍵)(沒有則按 score 排序)

score 和 max_score –相關性得分和最高得分(全文檢索用)

二、Query DSL

1、基本語法格式

Elasticsearch 提供了一個可以執行查詢的 Json 風格的 DSLdomain-specific language 領域特

定語言)。這個被稱為 Query DSL。

一個查詢語句的典型結構:

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

如果針對於某個欄位,那麼它的結構如下:

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

請求示例

GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "from":0,
  "size":5,
  "sort": [
    {
      "balance": {
        "order": "desc"
      }
    }
  ]
}
#query 定義如何查詢
#match_all 查詢型別【代表查詢所有的所有】,es 中可以在 query 中組合非常多的查詢型別完成複雜查詢
#除了 query 引數之外,我們也可以傳遞其它的引數以改變查詢結果。如 sort,size from+size 限定完成分頁
#sort 排序,多欄位排序,會在前序欄位相等時後續欄位內部排序,否則以前序為準

2、返回部分欄位

_source:需要返回哪些欄位寫在陣列中即可

響應結果

3、match【匹配查詢】

(1)對於基本資料型別的(非字串),進行精確匹配

GET bank/_search
{
  "query": {
    "match": {
      "account_number": 10
    }
  }
}
#match 返回 account_number=10 的

(2)對於字串型別的欄位,進行全文檢索,模糊匹配

GET bank/_search
{
  "query": {
    "match": {
      "address": "mill"
    }
  }
}
#最終查詢出 address 中包含 mill 單詞的所有記錄
#match 當搜尋字串型別的時候,會進行全文檢索,並且每條記錄有相關性得分

(3)字串,多個單詞(分詞+全文檢索)

GET bank/_search
{
  "query": {
    "match": {
      "address": "mill road"
    }
  }
}
#最終查詢出 address 中包含 mill 或者 road 或者 mill road 的所有記錄,並給出相關性得分(_score),也會按照這個評分排序

(4)精確匹配文字字串

GET bank/_search
{
  "query": {
    "match": {
      "address.keyword": " Mill road"
    }
  }
}
# 查詢 address完全為Mill Street 的資料

4、match_phrase【短語匹配】

將需要匹配的值當成一個整體單詞(不分詞)進行檢索

GET bank/_search
{
  "query": {
    "match_phrase": {
      "address": "mill road"
    }
  }
}
#查出 address 中包含 mill road 的所有記錄,並給出相關性得分

5、multi_match【多欄位匹配】

GET bank/_search
{
  "query": {
    "multi_match": {
      "query": "mill",
      "fields": [
        "city","address"
      ]
    }
  }
}
#檢索 city 或 address 匹配包含 mill 的資料,會對查詢條件分詞

6、bool【複合查詢】

bool 用來做複合查詢: 複合語句可以合併任何其它查詢語句,包括複合語句,複合語句之間可以互相巢狀,可以表達非常複雜的邏輯

(1)must:必須達到must所列舉的所有條件

GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {"match": {"firstname": "Forbes"}},
        {"match": {"gender": "M"}}
      ]
    }
  }
}

(2)must_not 必須不是指定的情況

GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {"match": {"firstname": "Forbes"}},
        {"match": {"gender": "M"}}
      ],
      "must_not": [
        {"match": {"lastname": "Wallace"}}
      ]
    }
  }
}

(3)should:應該達到 should列舉的條件

如果達到會增加相關文件的評分並不會改變 查詢的結果。如果 query 中只有 should 且只有一種匹配規則,那麼 should 的條件就會被作為預設匹配條件而去改變查詢結果

GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {"match": {"address": "mill"}},
        {"match": { "gender": "M" }}
      ],
      "should": [ {"match": { "address": "lane" }} ]
    }
  }
}
#應該匹配,匹配到能增加文件相關性得分,匹配不到也不會影響查詢結果

7、filter【結果過濾】

不是所有的查詢都需要計算相關性得分,僅用於 “filtering”(過濾)的文件。為了不計算分數 Elasticsearch 會自動檢查場景並且優化查詢的執行。

GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {"match": {"address": "mill"}}
      ],
      "filter": [
        {"range": {
          "balance": {
            "gte": 10000,
            "lte": 20000
          }
        }}
      ]
    }
  }
}
#range範圍查詢,大於1000小於20000

8、term精確檢索

避免使用 term 查詢文字欄位,預設情況下,Elasticsearch 會通過analysis分詞將文字欄位的值拆分為一部分,這使精確匹配文字欄位的值變得困難。如果要查詢文字欄位值,請使用 match 查詢代替。

和 match 一樣,匹配某個屬性的值。全文檢索欄位用 match其他非 text 欄位匹配用 term

GET bank/_search
{
  "query": {
    "term": {
      "age": "20"
    }
  }
}

9、Aggregation-執行聚合

聚合提供了從資料中分組和提取資料的能力。最簡單的聚合方法大致等於 SQL GROUP BY 和 SQL聚合函式。

詳細的介紹可以檢視官閘道器於Aggregation的文件,下面提供幾個示例來看一下聚合

https://www.elastic.co/guide/en/elasticsearch/reference/7.11/search-aggregations.html

(1)搜尋address中包含 mill的所有人的年齡分佈以及平均年齡,但不顯示這些人的詳情

GET bank/_search
{
  "query": {
    "match": {
      "address": "mill"
    }
  },
  "aggs": {
    "group_by_state": {
      "terms": {
        "field": "age"
      }
    },
    "avg_age":{
      "avg": {
        "field": "age"
      }
    }
  },
  "size": 0
}
#size:0 不顯示搜尋資料
#aggs:執行聚合。聚合語法如下:
#"aggs": {
    "aggs_name 這次聚合的名字,方便展示在結果集中": {
      "AGG_TYPE 聚合的型別(avg,term,terms)": {
        "field": "age"
      }
    }
 }

(2)按照年齡聚合,並且請求這些年齡段的這些人的平均薪資

GET bank/_search
{
  "query": {"match_all": {}},
  "aggs": {
    "group_by_state": {
      "terms": {
        "field": "age"
      },
      "aggs": {
        "avg_age": {
          "avg": {
            "field": "age"
            
          }
        }
      }
    }
  }
}
#其實就是aggs裡面又加了一個aggs,第二個aggs根據第一個aggs聚合後的結果在聚合

(3)查出所有年齡分佈,並且這些年齡段中 性別為M 的平均薪資和 性別為F 的平均薪資以及這個年齡

段的總體平均薪資

GET bank/_search
{
  "query": {"match_all": {}},
  "aggs": {
    "age_avg":{
      "terms": {
        "field": "age",
        "size": 1000
      },
      "aggs": {
        "gender_avg": {
          "terms": {
            "field": "gender.keyword",
            "size": 10
          },
          "aggs": {
            "balance_avg": {
              "avg": {
                "field": "balance"
              }
            }
          }
        },
        "balance_avg": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  }
}

相關文章