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 風格的 DSL(domain-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"
}
}
}
}
}
}