1. 程式人生 > >Elasticsearch入門四:Elasticsearch-搜尋、過濾、聚合

Elasticsearch入門四:Elasticsearch-搜尋、過濾、聚合


title: Elasticsearch入門四:Elasticsearch-搜尋、過濾、聚合(譯)
date: 2018-11-01 17:00:00
tags: Elasticsearch

原文地址:

https://www.elastic.co/guide/en/elasticsearch/reference/current/_exploring_your_data.html

一.搜尋 API

搜尋的REST API可以從_search端點訪問。這個示例返回customer索引中的所有文件:

GET /event_search/_search?q=*&sort=id:asc&pretty

幾個搜尋引數的意思:

  • q=* :匹配索引中的所有文件

  • sort=id:asc : 所有文件按照id升序排序

  • pretty : 格式化JSON輸出

響應如下:

{
	"took" : 207,
	"timed_out" : false,
	"_shards" : {
		"total" : 5,
		"successful" : 5,
		"failed" : 0
	},

	"hits" : {
		"total" : 16107987,
		"max_score" : null,
		"hits" : [
 	 	{
    		"_index" : "event_search",
    		"_type" : "app_sjyx_event",
    		"_id" : "00000092-bda7-48de-80ef-1cee534aa5e7",
    		"_score" : null,
   			"_source" : {
      			"id" : "00000092-bda7-48de-80ef-1cee534aa5e7",
      			"event" : "wxid_winbzgzpq7fg12:我今天把超夢種族一弄"
    		},
    		"sort" : [
      			"00000092-bda7-48de-80ef-1cee534aa5e7"
    		]
  		},
		{
    		"_index" : "event_search",
    		"_type" : "app_sjyx_event",
    		"_id" : "00000111-9a7c-483e-80fb-3313a4c9a8ce",
    		"_score" : null,
    		"_source" : {
      			"id" : "00000111-9a7c-483e-80fb-3313a4c9a8ce",
      			"event" : "通話時長 03:38"
    		},
    		"sort" : [
      			"00000111-9a7c-483e-80fb-3313a4c9a8ce"
   	 		]
  		}
 	]
 }
}

關於響應,我們看到以下部分:

  • took – 搜尋時間(毫秒)

  • timed_out – 搜尋是否超時

  • _shards – 告訴我們搜尋了多少碎片,以及成功/失敗搜尋碎片的計數

  • hits – 搜尋結果

  • hits.total – 符合我們搜尋條件的檔案總數

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

  • hits.sort 結果的排序鍵(如果按分數排序,則會丟失)

使用以下的方法可以達到相同的搜尋結果:

POST /event_search/_search
{
	"query": { "match_all": {} },
	"sort": [
		{ "id": "asc" }
	]
}

很重要的一點是,一旦返回搜尋結果,Elasticsearch就完全完成了對請求的處理,不會在結果中維護任何型別的伺服器端資源或開啟遊標,這不同於SQL。

二.查詢 DSL

查詢DSL是json風格的域特定查詢語句,查詢語句非常全面,我們先從幾個基本的例子入手。

1.按id升序查詢10到19的文件

POST /event_search/_search
{
	"query": { "match_all": {} },
	"sort": [
		{ "id": "asc" }
	],
	"from": 10,
	"size": 10
}

搜尋引數含義:

  • “query”:查詢引數,match_all 指搜尋所有的索引

  • “sort”:排序規則

  • “from”:指定從哪個文件索引開始,預設為0

  • “size”:指定從from引數開始返回多少文件

2.查詢event欄位中包含喜歡或推銷的文件,文件只返回id,event兩個欄位

POST /event_search/_search
{
	 "query": { "match": { "event": "喜歡 推銷" } },
	 "_source": ["id", "event"]
}
  • “_source”:指定返回的欄位

3.查詢event欄位中包含喜歡且包含推銷的文件

POST /event_search/_search
{
	"query": { "match_phrase": { "event": "喜歡 推銷" } }
}

由以上兩例可以看出match查詢條件是的關係,而match_phrase查詢條件是的關係

4.bool查詢語句

bool查詢允許我們使用布林邏輯將較小的查詢組合成較大的查詢

以下例子包含兩個匹配查詢,並返回地址中包含“mill”“lane”的所有帳戶:

GET /bank/_search
{
	"query": {
	"bool": {
  		"must": [
    		{ "match": { "address": "mill" } },
    		{ "match": { "address": "lane" } }
  		 ]
		}
	}
}

與此相反,這個示例包含兩個匹配查詢,並返回地址中包含“mill”“lane”的所有帳戶:

GET /bank/_search
{
	"query": {
	"bool": {
  		"should": [
   			 { "match": { "address": "mill" } },
    		 { "match": { "address": "lane" } }
  		]
	 }
	}
}

這個示例包含兩個匹配查詢,並返回地址中既不包含“mill”也不包含“lane”的所有帳戶:

GET /bank/_search
{
	"query": {
	"bool": {
  		"must_not": [
    		{ "match": { "address": "mill" } },
    		{ "match": { "address": "lane" } }
  		]
		}
 	}
}

這個示例返回所有40歲但不生活在ID(阿霍)中的人的帳戶:

GET /bank/_search
{
	"query": {
	"bool": {
  	"must": [
    	{ "match": { "age": "40" } }
  	],
  	"must_not": [
    		{ "match": { "state": "ID" } }
  		]
	}
   }
}

三.過濾器

在上一節中,我們跳過了一個名為document score(搜尋結果中的_score欄位)的小細節。分數是一個數值,它是文件與我們指定的搜尋查詢匹配程度的相對度量。分數越高,文件越相關,分數越低,文件越不相關。

但是查詢並不總是需要產生scores,特別是當它們僅用於“過濾”文件集時。Elasticsearch檢測到這些情況並自動優化查詢執行,以便不計算無用的分數。

我們在前一節中介紹的bool查詢還支援filter子句,該子句允許使用查詢來限制其他子句匹配的文件,而不改變計算分數的方式。作為一個例子,讓我們引入range查詢,它允許我們通過一系列值篩選文件。這通常用於數字或日期過濾。

以下示例使用bool查詢返回所有餘額在20000到30000之間的帳戶(包括在內)。換句話說,我們希望找到的賬戶餘額大於等於20000,小於等於30000:

GET /bank/_search
{
	"query": {
		"bool": {
  			"must": { "match_all": {} },
  			"filter": {
    			"range": {
      				"balance": {
        				"gte": 20000,
        				"lte": 30000
      					}
    				  }
  					}
				}
		   }
}

四.聚合

聚合提供了從資料中分組和提取統計資訊的能力。考慮聚合最簡單的方法是將其大致等同於SQL GROUP by和SQL聚合函式。在Elasticsearch中,您可以執行返回命中的搜尋,同時在一個響應中返回與所有命中分離的聚合結果。這在某種意義上非常強大和高效,因為您可以執行查詢和多個聚合,並一次性獲得兩個(或兩個以上)操作的結果,從而減少網路資源呼叫的損耗。

首先,這個示例按狀態對所有帳戶進行分組,然後返回按計數遞減排序的前10個(預設):

GET /bank/_search
{
	"size": 0,
	"aggs": {
		"group_by_state": {
  		"terms": {
    		"field": "state"
  		 }
	 	}
	}
}

在SQL中,上述聚合的概念類似於:

SELECT state, COUNT(*) FROM bank GROUP BY state ORDER BY COUNT(*) DESC LIMIT 10;

響應(部分顯示):

 {
	"took": 29,
	"timed_out": false,
	"_shards": {
		"total": 5,
		"successful": 5,
		"skipped" : 0,
		"failed": 0
	},
	"hits" : {
		"total" : 1000,
		"max_score" : 0.0,
		"hits" : [ ]
	},
	"aggregations" : {
		"group_by_state" : {
  		"doc_count_error_upper_bound": 20,
  		"sum_other_doc_count": 770,
  		"buckets" : [ {
    		"key" : "ID",
    		"doc_count" : 27
  		}, {
    		"key" : "TX",
    		"doc_count" : 27
  		}, {
    		"key" : "AL",
    		"doc_count" : 25
 		}, {
    		"key" : "MD",
    		"doc_count" : 25
  		}, {
    		"key" : "TN",
    		"doc_count" : 23
  	    }, {
    		"key" : "MA",
    		"doc_count" : 21
 	   	}, {
    		"key" : "NC",
   			"doc_count" : 21
  	  	}, {
    		"key" : "ND",
    		"doc_count" : 21
  		}, {
    		"key" : "ME",
    		"doc_count" : 20
  		}, {
    		"key" : "MO",
    		"doc_count" : 20
  		} ]
  	  }
	}
}

我們可以看到ID(愛達荷州)有27個賬戶,TX(德克薩斯州)有27個賬戶,AL(阿拉巴馬州)有25個賬戶,等等。

注意,我們將size=0設定為不顯示搜尋結果,因為我們只想看到響應中的聚合結果。

注意我們如何將average_balance聚合巢狀到group_by_state聚合中。這是所有聚合的常見模式。

在前面的聚合的基礎上,現在讓我們按降序對平均餘額進行排序:

GET /bank/_search
{
	"size": 0,
	"aggs": {
		"group_by_state": {
 		"terms": {
    		"field": "state",
    		"order": {
      			"average_balance": "desc"
   			 }
  		},
 	   "aggs": {
       "average_balance": {
      	 "avg": {
        	"field": "balance"
      		}
       	}
   	  }
    }
  }
}

這個例子展示了我們如何根據年齡等級(20-29歲,30-39歲,40-49歲)來分組,然後根據性別,最後得到平均賬戶餘額,每個年齡等級,每個性別:

GET /bank/_search
{
	"size": 0,
	"aggs": {
		"group_by_age": {
  		"range": {
    		"field": "age",
    		"ranges": [
      		{
        		"from": 20,
        		"to": 30
      		},
     		{
        		"from": 30,
        		"to": 40
      		},
      		{
        		"from": 40,
        		"to": 50
      		}
    	 ]
  		},
  		"aggs": {
   		"group_by_gender": {
      	"terms": {
        	"field": "gender"
      	},
      	"aggs": {
        	"average_balance": {
          	"avg": {
            	"field": "balance"
          	  }
           }
        }
      }
    }
   }
  }
}

還有很多其他的聚合功能我們在這裡不會詳細介紹。如果您想做進一步的實驗,聚合參考指南是一個很好的起點。

五.總結

Elasticsearch是一個簡單的和複雜的產品。到目前為止,我們已經瞭解了它是什麼,如何檢視它的內部,以及如何使用一些REST api使用它。希望本教程能讓您更好地理解Elasticsearch是什麼,更重要的是,它激發了您對其其他強大功能的進一步試驗!