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是什麼,更重要的是,它激發了您對其其他強大功能的進一步試驗!