平時使用Elasticsearch的時候,會在Kibana中使用Query DSL來查詢數據.每次要用到Query DSL時都基本忘光了,需要重新在回顧一遍,最近發現Elasticsearch已經支持SQL查詢了(6.3版本以后),整理了下一些用法.
簡介
Elasticsearch SQL是一個X-Pack組件,它允許針對Elasticsearch實時執行類似SQL的查詢.無論使用REST接口,命令行還是JDBC,任何客戶端都可以使用SQL對Elasticsearch中的數據進行原生搜索和聚合數據.可以將Elasticsearch SQL看作是一種翻譯器,它可以將SQL翻譯成Query DSL.
Elasticsearch SQL具有如下特性:
- 原生支持:Elasticsearch SQL是專門為Elasticsearch打造的.
- 沒有額外的零件:無需其他硬件,處理器,運行環境或依賴庫即可查詢Elasticsearch,Elasticsearch SQL直接在Elasticsearch內部運行.
- 輕巧高效:Elasticsearch SQL并未抽象化其搜索功能,相反的它擁抱并接受了SQL來實現全文搜索,以簡潔的方式實時運行全文搜索.
準備
先安裝好Elasticsearch和Kibana,這里安裝的是7.17.0版本
安裝完成后在Kibana中 http://127.0.0.1:5601/app/dev_tools#/console{target=“_blank”}
導入測試數據,數據地址: https://github.com/macrozheng/mall-learning/blob/master/document/json/accounts.json{target=“_blank”}
直接在Kibana的Dev Tools中運行如下命令即可:
POST /account/_bulk
{"index":{"_id":"1"}}
{"account_number":1,"balance":39225,"firstname":"Amber","lastname":"Duke","age":32,"gender":"M","address":"880 Holmes Lane","employer":"Pyrami","email":"amberduke@pyrami.com","city":"Brogan","state":"IL"}
{"index":{"_id":"6"}}
{"account_number":6,"balance":5686,"firstname":"Hattie","lastname":"Bond","age":36,"gender":"M","address":"671 Bristol Street","employer":"Netagy","email":"hattiebond@netagy.com","city":"Dante","state":"TN"}
{"index":{"_id":"13"}}
{"account_number":13,"balance":32838,"firstname":"Nanette","lastname":"Bates","age":28,"gender":"F","address":"789 Madison Street","employer":"Quility","email":"nanettebates@quility.com","city":"Nogal","state":"VA"}
{"index":{"_id":"18"}}
{"account_number":18,"balance":4180,"firstname":"Dale","lastname":"Adams","age":33,"gender":"M","address":"467 Hutchinson Court","employer":"Boink","email":"daleadams@boink.com","city":"Orick","state":"MD"}
{"index":{"_id":"20"}}
{"account_number":20,"balance":16418,"firstname":"Elinor","lastname":"Ratliff","age":36,"gender":"M","address":"282 Kings Place","employer":"Scentric","email":"elinorratliff@scentric.com","city":"Ribera","state":"WA"}
{"index":{"_id":"25"}}
{"account_number":25,"balance":40540,"firstname":"Virginia","lastname":"Ayala","age":39,"gender":"F","address":"171 Putnam Avenue","employer":"Filodyne","email":"virginiaayala@filodyne.com","city":"Nicholson","state":"PA"}
{"index":{"_id":"32"}}
{"account_number":32,"balance":48086,"firstname":"Dillard","lastname":"Mcpherson","age":34,"gender":"F","address":"702 Quentin Street","employer":"Quailcom","email":"dillardmcpherson@quailcom.com","city":"Veguita","state":"IN"}
{"index":{"_id":"37"}}
{"account_number":37,"balance":18612,"firstname":"Mcgee","lastname":"Mooney","age":39,"gender":"M","address":"826 Fillmore Place","employer":"Reversus","email":"mcgeemooney@reversus.com","city":"Tooleville","state":"OK"}
{"index":{"_id":"44"}}
{"account_number":44,"balance":34487,"firstname":"Aurelia","lastname":"Harding","age":37,"gender":"M","address":"502 Baycliff Terrace","employer":"Orbalix","email":"aureliaharding@orbalix.com","city":"Yardville","state":"DE"}
{"index":{"_id":"49"}}
{"account_number":49,"balance":29104,"firstname":"Fulton","lastname":"Holt","age":23,"gender":"F","address":"451 Humboldt Street","employer":"Anocha","email":"fultonholt@anocha.com","city":"Sunriver","state":"RI"}
第一個SQL查詢
我們使用SQL來查詢下前10條記錄,可以通過format參數控制返回結果的格式,txt表示文本格式,看起來更直觀點,默認為json格式.
在Kibana的Dev Tools中輸入如下命令:
POST /_sql?format=txt
{"query": "SELECT account_number,address,age,balance FROM account LIMIT 10"
}
查詢結果顯示如下.
account_number | address | age | balance
---------------+--------------------+---------------+---------------
1 |880 Holmes Lane |32 |39225
6 |671 Bristol Street |36 |5686
13 |789 Madison Street |28 |32838
18 |467 Hutchinson Court|33 |4180
20 |282 Kings Place |36 |16418
25 |171 Putnam Avenue |39 |40540
32 |702 Quentin Street |34 |48086
37 |826 Fillmore Place |39 |18612
44 |502 Baycliff Terrace|37 |34487
49 |451 Humboldt Street |23 |29104
如上實例,使用 _sql
指明使用SQL模塊,在 query
字段中指定要執行的SQL語句.使用 format
指定返回數據的格式,數據格式可選項有以下幾個,它們都是見名識意的:
format | Accept Http header | 說明 |
---|---|---|
csv | text/csv | 逗號分隔 |
json | application/json | Json 格式 |
tsv | text/tab-separated-values | tab 分隔 |
txt | text/plain | 文本格式 |
yaml | application/yaml | yaml |
cbor | application/cbor | 簡潔的二進制對象表示格式 |
smile | application/smile | 類似于 cbor 的另一種二進制格式 |
將SQL轉化為DSL
當我們需要使用Query DSL時,也可以先使用SQL來查詢,然后通過Translate API轉換即可.
例如我們翻譯以下查詢語句:
POST /_sql/translate
{"query": "SELECT account_number,address,age,balance FROM account WHERE age>32 LIMIT 10"
}
最終獲取到Query DSL結果如下.
{"size" : 10,"query" : {"range" : {"age" : {"from" : 32,"to" : null,"include_lower" : false,"include_upper" : false,"boost" : 1.0}}},"_source" : false,"fields" : [{"field" : "account_number"},{"field" : "address"},{"field" : "age"},{"field" : "balance"}],"sort" : [{"_doc" : {"order" : "asc"}}]
}
然后可以用Query DSL 語法來查詢:
GET /account/_search
{"size": 10,"query": {"range": {"age": {"from": 32,"to": null,"include_lower": false,"include_upper": false,"boost": 1}}},"_source": false,"fields": [{"field": "account_number"},{"field": "address"},{"field": "age"},{"field": "balance"}],"sort": [{"_doc": {"order": "asc"}}]
}
SQL和DSL混合使用
我們還可以將SQL和Query DSL混合使用,比如使用Query DSL來設置過濾條件.
例如查詢 age在30-35
之間的記錄,可以使用如下查詢語句:
POST /_sql?format=txt
{"query": "SELECT account_number,address,age,balance FROM account","filter": {"range": {"age": {"gte": 30,"lte": 35}}},"fetch_size": 10
}
SQL和ES對應關系
雖然 SQL 和 Elasticsearch 對于數據的組織方式(以及不同的語義)有不同的術語,但本質上它們的用途是相同的.下面是它們的映射關系表:
SQL | Elasticsearch | 說明 |
---|---|---|
column | field | 在 Elasticsearch 字段時,SQL 將這樣的條目調用為 column.注意,在 Elasticsearch,一個字段可以包含同一類型的多個值(本質上是一個列表) ,而在 SQL 中,一個列可以只包含一個表示類型的值.Elasticsearch SQL 將盡最大努力保留 SQL 語義,并根據查詢的不同,拒絕那些返回多個值的字段. |
row | document | 列和字段本身不存在; 它們是行或文檔的一部分.兩者的語義略有不同: 行row往往是嚴格的(并且有更多的強制執行),而文檔往往更靈活或更松散(同時仍然具有結構). |
table | index | 在 SQL 還是 Elasticsearch 中查詢針對的目標 |
schema | implicit | 在關系型數據庫中,schema 主要是表的名稱空間,通常用作安全邊界.Elasticsearch沒有為它提供一個等價的概念. |
雖然這些概念之間的映射在語義上有些不同,但它們間更多的是有共同點,而不是不同點.
詞法結構
ES SQL 的詞法結構很大程度上類似于 ANSI SQL 本身.ES SQL 當前一次只能接受一個命令,這里的命令是由輸入流結尾結束的 token 序列.這些 token 可以是關鍵字,標識符(帶引號或者不帶引號),文本(或者常量),特殊字符符號(通常是分隔符).
關鍵字
關鍵詞這個其實跟我們寫 SQL 語句那種關鍵字的定義是一樣的,例如 SELECT,FROM 等都是關鍵字,需要注意的是,關鍵字不區分大小寫.
SELECT * FROM my_table
如上示例,共有 4 個 token:SELECT, * ,FROM ,my_table
,其中 SELECT,* ,FROM
是關鍵詞,表示在 SQL 具有固定含義的詞.而 my_table
是一個標識符,其表示了 SQL 中實體,如表,列等
標識符
標識符有兩種類型:帶引號的和不帶引號的,示例如下:
SELECT ip_address FROM "hosts-*"
如上示例,查詢中有兩個標識符分別為不帶引號的 ip_address
和帶引號的 hosts-*
(通配符模式).
因為 ip_address
不與任何關鍵字沖突,所以可以不帶引號.而 hosts-*
與 -
(減號操作)和 *
沖突,所以要加引號.
📝注意: 對于標識符來說,應該盡量避免使用復雜的命名和與關鍵字沖突的命名,并且在輸入的時候使用引號作為標識符,這樣可以消除歧義.
直接常量
ES SQL 支持兩種隱式的類型常量:字符串 和 數字.
- 字符串,字符串可以用單引號進行限定,例如:
'mysql'
.如果在字符串中包含了單引號,則需要使用另一個單引號進行轉義,例如:'Captain EO''s Voyage'
. - 數值常量,數值常量可以使用十進制和科學計數法進行表示,其示例如下:
1969 -- integer notation
3.14 -- decimal notation
.1234 -- decimal notation starting with decimal point
4E5 -- scientific notation (with exponent marker)
1.2e-3 -- scientific notation with decimal point
一個包含小數點的數值常量會被解析為 Double 類型.如果適合解析為整型,則解析為 Integer,否則解析為長整型(Long).
單引號,雙引號
在 SQL 中,單引號和雙引號具有不同的含義,不能互換使用.單引號用于聲明字符串,而雙引號用于表示標識符.示例如下:
SELECT "first_name" FROM "musicians" WHERE "last_name" = 'Carroll'
如上示例,first_name,musicians,last_name
都是標識符,用雙引號.而 Carroll 是字符串,用單引號.
特殊字符
一些非數字和字母的字符具有不同于運算符的專用含義,特殊字符有:
字符 | 描述 |
---|---|
* | 在一些上下文中表示數據表的所有字段,也可以表示某些聚合函數的參數. |
, | 用于列舉列表的元素 |
. | 用于數字常量或者分隔標識符限定符(表,列等) |
() | 用于特定的 SQL 命令,函數聲明,或者強制優先級. |
運算符
ES SQL 中大多數的運算符它們的優先級都是相同的,并且是左關聯.如果需要修改優先級,則要用括號來強制改變其優先級.下表是 ES SQL 支持的運算符和其優先級:
運算符 | 結合性 | 說明 |
---|---|---|
. | 左結合 | 限定符或者分割符 |
:: | 左結合 | PostgreSQL-style 風格的類型轉換符 |
+ - | 右結合 | 一元加減符 |
* / % | 左結合 | 乘法,除法,取模 |
+ - | 左結合 | 加法,減法運算 |
BETWEEN IN LIKE | 范圍包含,字符匹配 | |
< > <= >= = <=> <> != | 比較運算 | |
NOT | 右結合 | 邏輯非 |
AND | 左結合 | 邏輯與 |
OR | 左結合 | 邏輯或 |
注釋
ES SQL 支持兩種注釋:單行和多行注釋,其示例如下:
-- single line comment,單行注釋/* multilinecommentthat supports /* nested comments */多行注釋*/
常用SQL操作
語法介紹
在ES中使用SQL查詢的語法與在數據庫中使用基本一致,具體格式如下:
SELECT select_expr [, ...]
[ FROM table_name ]
[ WHERE condition ]
[ GROUP BY grouping_element [, ...] ]
[ HAVING condition]
[ ORDER BY expression [ ASC | DESC ] [, ...] ]
[ LIMIT [ count ] ]
[ PIVOT ( aggregation_expr FOR column IN ( value [ [ AS ] alias ] [, ...] ) ) ]
WHERE
可以使用WHERE
語句設置查詢條件,比如查詢state字段為VA的記錄,查詢語句如下.
POST /_sql?format=txt
{"query": "SELECT account_number,address,age,balance,state FROM account WHERE state='VA' LIMIT 10"
}
查詢結果如下:
account_number | address | age | balance | state
---------------+--------------------+---------------+---------------+---------------
13 |789 Madison Street |28 |32838 |VA
486 |991 Applegate Court |22 |35902 |VA
703 |489 Flatlands Avenue|29 |27443 |VA
835 |641 Royce Street |25 |46558 |VA
897 |731 Poplar Street |25 |45973 |VA
564 |842 Congress Street |22 |43631 |VA
588 |301 Anna Court |31 |43531 |VA
660 |916 Amersfort Place |33 |46427 |VA
797 |919 Quay Street |26 |6854 |VA
836 |953 Dinsmore Place |25 |20797 |VA
GROUP BY
我們可以使用 GROUP BY
語句對數據進行分組,統計出分組記錄數量,最大age和平均balance等信息,查詢語句如下.
POST /_sql?format=txt
{"query": "SELECT state,COUNT(*),MAX(age),AVG(balance) FROM account GROUP BY state LIMIT 10"
}
HAVING
我們可以使用 HAVING
語句對分組數據進行二次篩選,比如篩選分組記錄數量大于15的信息,查詢語句如下.
POST /_sql?format=txt
{"query": "SELECT state,COUNT(*),MAX(age),AVG(balance) FROM account GROUP BY state HAVING COUNT(*)>15 LIMIT 10"
}
查詢結果如下:
state | COUNT(*) | MAX(age) | AVG(balance)
---------------+---------------+---------------+------------------
AK |22 |40 |26131.863636363636
AL |25 |40 |25739.56
AR |18 |39 |27238.166666666668
CA |17 |40 |22517.882352941175
CT |16 |39 |28278.4375
DC |24 |40 |23180.583333333332
FL |18 |38 |20443.444444444445
ORDER BY
我們可以使用ORDER BY
語句對數據進行排序,比如按照balance字段從高到低排序,查詢語句如下.
POST /_sql?format=txt
{"query": "SELECT account_number,address,age,balance,state FROM account ORDER BY balance DESC LIMIT 10 "
}
查詢結果如下:
account_number | address | age | balance | state
---------------+----------------------+---------------+---------------+---------------
248 |717 Hendrickson Place |36 |49989 |WA
854 |603 Cooper Street |25 |49795 |AL
240 |659 Highland Boulevard|35 |49741 |NH
97 |512 Cumberland Walk |40 |49671 |MO
842 |833 Bushwick Court |23 |49587 |TX
168 |975 Flatbush Avenue |20 |49568 |IL
803 |963 Highland Avenue |25 |49567 |MS
926 |833 Quincy Street |21 |49433 |VT
954 |688 Hart Street |22 |49404 |MD
572 |994 Chester Court |20 |49355 |UT
DESCRIBE
我們可以使用 DESCRIBE
語句查看表(ES中為索引)中有哪些字段,比如查看account表的字段,查詢語句如下.
POST /_sql?format=txt
{"query": "DESCRIBE account"
}
查詢結果如下:
column | type | mapping
-----------------+---------------+---------------
account_number |BIGINT |long
address |VARCHAR |text
address.keyword |VARCHAR |keyword
age |BIGINT |long
balance |BIGINT |long
city |VARCHAR |text
city.keyword |VARCHAR |keyword
email |VARCHAR |text
email.keyword |VARCHAR |keyword
employer |VARCHAR |text
employer.keyword |VARCHAR |keyword
firstname |VARCHAR |text
firstname.keyword|VARCHAR |keyword
gender |VARCHAR |text
gender.keyword |VARCHAR |keyword
lastname |VARCHAR |text
lastname.keyword |VARCHAR |keyword
state |VARCHAR |text
state.keyword |VARCHAR |keyword
SHOW TABLES
我們可以使用 SHOW TABLES
查看所有的表(ES中為索引).
POST /_sql?format=txt
{"query": "SHOW TABLES"
}
查詢結果如下:
#! this request accesses system indices: [.kibana_7.17.0_001, .kibana_task_manager_7.17.0_001], but in a future major version, direct access to system indices will be prevented by default
#! this request accesses system indices: [.apm-agent-configuration, .apm-custom-link, .async-search, .kibana_7.17.0_001, .kibana_task_manager_7.17.0_001, .tasks], but in a future major version, direct access to system indices will be prevented by defaultcatalog | name | type | kind
---------------+-------------------------------+---------------+---------------
my-application |.apm-agent-configuration |TABLE |INDEX
my-application |.apm-custom-link |TABLE |INDEX
my-application |.async-search |TABLE |INDEX
my-application |.kibana |VIEW |ALIAS
my-application |.kibana_7.17.0 |VIEW |ALIAS
my-application |.kibana_7.17.0_001 |TABLE |INDEX
my-application |.kibana_task_manager |VIEW |ALIAS
my-application |.kibana_task_manager_7.17.0 |VIEW |ALIAS
my-application |.kibana_task_manager_7.17.0_001|TABLE |INDEX
my-application |.tasks |TABLE |INDEX
my-application |account |TABLE |INDEX
my-application |kibana_sample_data_flights |TABLE |INDEX
支持的函數
使用SQL查詢ES中的數據,不僅可以使用一些SQL中的函數,還可以使用一些ES中特有的函數.
查詢支持的函數
我們可以使用 SHOW FUNCTIONS
語句查看所有支持的函數,比如搜索所有帶有 DATE
字段的函數可以使用如下語句.
POST /_sql?format=txt
{"query": "SHOW FUNCTIONS LIKE '%DATE%'"
}
查詢結果如下:
name | type
---------------+---------------
CURDATE |SCALAR
CURRENT_DATE |SCALAR
DATEADD |SCALAR
DATEDIFF |SCALAR
DATEPART |SCALAR
DATETIME_FORMAT|SCALAR
DATETIME_PARSE |SCALAR
DATETRUNC |SCALAR
DATE_ADD |SCALAR
DATE_DIFF |SCALAR
DATE_PARSE |SCALAR
DATE_PART |SCALAR
DATE_TRUNC |SCALAR
全文搜索函數
全文搜索函數是ES中特有的,當使用 MATCH
或 QUERY
函數時,會啟用全文搜索功能,SCORE
函數可以用來統計搜索評分.
MATCH()
使用MATCH
函數查詢address中包含Street的記錄.
POST /_sql?format=txt
{"query": "SELECT account_number,address,age,balance,SCORE() FROM account WHERE MATCH(address,'Street') LIMIT 10"
}
查詢結果如下:
account_number | address | age | balance | SCORE()
---------------+-----------------------+---------------+---------------+---------------
6 |671 Bristol Street |36 |5686 |0.95395315
13 |789 Madison Street |28 |32838 |0.95395315
32 |702 Quentin Street |34 |48086 |0.95395315
49 |451 Humboldt Street |23 |29104 |0.95395315
51 |334 River Street |31 |14097 |0.95395315
63 |510 Sedgwick Street |30 |6077 |0.95395315
87 |446 Halleck Street |22 |1133 |0.95395315
107 |694 Jefferson Street |28 |48844 |0.95395315
138 |422 Malbone Street |39 |9006 |0.95395315
140 |878 Schermerhorn Street|32 |26696 |0.95395315
QUERY()
使用 QUERY
函數查詢address中包含Street的記錄.
POST /_sql?format=txt
{"query": "SELECT account_number,address,age,balance,SCORE() FROM account WHERE QUERY('address:Street') LIMIT 10"
}
查詢結果如下:
account_number | address | age | balance | SCORE()
---------------+-----------------------+---------------+---------------+---------------
6 |671 Bristol Street |36 |5686 |0.95395315
13 |789 Madison Street |28 |32838 |0.95395315
32 |702 Quentin Street |34 |48086 |0.95395315
49 |451 Humboldt Street |23 |29104 |0.95395315
51 |334 River Street |31 |14097 |0.95395315
63 |510 Sedgwick Street |30 |6077 |0.95395315
87 |446 Halleck Street |22 |1133 |0.95395315
107 |694 Jefferson Street |28 |48844 |0.95395315
138 |422 Malbone Street |39 |9006 |0.95395315
140 |878 Schermerhorn Street|32 |26696 |0.95395315
SQL CLI
如果你不想使用Kibana來使用ES SQL的話,也可以使用ES自帶的SQL CLI來查詢,該命令位于ES的bin目錄下.
使用如下命令啟動SQL CLI:
elasticsearch-sql-cli http://localhost:9200
然后直接輸入SQL命令即可查詢了,注意要加分號.
SELECT account_number,address,age,balance FROM account LIMIT 10;
ES SQL 的局限性
使用SQL查詢ES有一定的局限性,沒有原生的Query DSL那么強大,對于嵌套屬性和某些函數的支持并不怎么好,但是平時用來查詢下數據基本夠用了.
ES SQL 使用實戰
我們先準備數據,此處我們將使用 Kibana 提供的航班數據:
如下圖,在 Kibana 中點擊左邊欄的 Analytics
下的 Overview
,右邊的頁面中選擇 DashBoard
然后點擊 Install some sample data
鏈接,
再點擊 Sample flight data
即可加入航班的數據.
可以使用以下語句查看航班數據:
POST /kibana_sample_data_flights/_search
{"query": {"match_all": {}}
}
下面來看看常用的 SQL 如何編寫.
1. WHERE
我們過濾出目的地為 US 的數據:
POST /_sql?format=txt
{"query": "SELECT FlightNum, OriginWeather, OriginCountry, Carrier FROM kibana_sample_data_flights WHERE DestCountry = 'US'"
}
查詢結果如下:
FlightNum | OriginWeather | OriginCountry | Carrier
---------------+-------------------+---------------+----------------
R43CELD |Cloudy |US |JetBeats
3YAQM9U |Clear |US |JetBeats
8SHQI41 |Cloudy |US |JetBeats
HF9AP10 |Sunny |US |JetBeats
ZTL6FPB |Heavy Fog |IT |ES-Air
TF9BTQL |Clear |JP |Kibana Airlines
T9QK7GX |Clear |IN |Logstash Airways
4AHGESO |Rain |ZA |Kibana Airlines
J684XSR |Sunny |AR |JetBeats
T390OH4 |Cloudy |IN |ES-Air
Q33SYKK |Sunny |KR |JetBeats
JBQ50Y2 |Clear |IT |Logstash Airways
2. GROUP BY
可以使用 GROUP BY 語句對數據進行分組聚合統計操作,例如查詢航班分組的平均飛行距離等.其示例如下:
POST /_sql?format=txt
{"query": "SELECT count(*),max(DistanceMiles), avg(DistanceMiles) FROM kibana_sample_data_flights GROUP BY DestCountry"
}
如上示例,我們以目的地國家進行分組,然后統計每個分組的數量,最大的飛行距離,平均飛行距離.其結果如下:
count(*) |max(DistanceMiles)|avg(DistanceMiles)
---------------+------------------+------------------
46 |7600.7158203125 |3233.800320625305
305 |12140.8603515625 |6603.605808945953
377 |9917.6455078125 |3128.910634331741
416 |10832.3994140625 |7915.6610843951885
944 |10600.296875 |4077.664177652133
691 |10293.208984375 |2775.8247816469493
45 |12075.3935546875 |7542.028591579861
1096 |12353.7802734375 |5037.134736095902
91 |10000.7255859375 |5683.497867123111
278 |10030.87109375 |3448.2222546090325
48 |9670.9072265625 |3278.826272328695
237 |10575.1279296875 |5419.154288118902
15 |10346.84765625 |3214.9680114746093
3. HAVING
可以使用 HAVING 對分組的數據進行二次篩選,比如篩選分組中記錄數大于 100 的數據,其結果如下:
POST /_sql?format=txt
{"query": "SELECT count(*),max(DistanceMiles), avg(DistanceMiles) FROM kibana_sample_data_flights GROUP BY DestCountry HAVING COUNT(*) > 100"
}
我們過濾出了分組中記錄數大于 100 的數據,其結果如下:
count(*) |max(DistanceMiles)|avg(DistanceMiles)
---------------+------------------+------------------
305 |12140.8603515625 |6603.605808945953
377 |9917.6455078125 |3128.910634331741
416 |10832.3994140625 |7915.6610843951885
944 |10600.296875 |4077.664177652133
691 |10293.208984375 |2775.8247816469493
1096 |12353.7802734375 |5037.134736095902
278 |10030.87109375 |3448.2222546090325
237 |10575.1279296875 |5419.154288118902
449 |10282.5048828125 |3213.2889483309536
373 |10774.0 |5064.675941446831
4. ORDER BY
我們可以使用 ORDER BY 進行排序,例如將平均飛行距離降序排序,其結果如下:
POST /_sql?format=txt
{"query": "SELECT count(*),max(DistanceMiles), avg(DistanceMiles) as avgDistance FROM kibana_sample_data_flights GROUP BY DestCountry HAVING COUNT(*) > 100 ORDER BY avgDistance desc"
}
如上示例,我們將數據用平均距離排序,其結果為
count(*) |max(DistanceMiles)| avgDistance
---------------+------------------+------------------
416 |10832.3994140625 |7915.6610843951885
305 |12140.8603515625 |6603.605808945953
283 |10556.7587890625 |6030.0211101842015
237 |10575.1279296875 |5419.154288118902
214 |11447.2265625 |5323.084783429297
774 |11407.380859375 |5280.042444507589
116 |10553.98828125 |5118.16688169282
373 |10774.0 |5064.675941446831
5. 分頁
分頁有多種實現方式,可以使用 limit,top,fetch_size 來進行分頁.
1,使用limit
分頁操作
POST /_sql?format=txt
{"query": "SELECT FlightNum, OriginWeather, OriginCountry, Carrier FROM kibana_sample_data_flights WHERE DestCountry = 'US' limit 10"
}
2,使用 top
進行分頁
POST /_sql?format=txt
{"query": "SELECT top 10 FlightNum, OriginWeather, OriginCountry, Carrier FROM kibana_sample_data_flights WHERE DestCountry = 'US'"
}
3,使用 fetch_size
進行分頁
POST /_sql?format=txt
{"query": "SELECT FlightNum, OriginWeather, OriginCountry, Carrier FROM kibana_sample_data_flights WHERE DestCountry = 'US'","fetch_size": 10
}
其結果如下:
FlightNum | OriginWeather | OriginCountry | Carrier
---------------+---------------+---------------+----------------
R43CELD |Cloudy |US |JetBeats
3YAQM9U |Clear |US |JetBeats
8SHQI41 |Cloudy |US |JetBeats
HF9AP10 |Sunny |US |JetBeats
ZTL6FPB |Heavy Fog |IT |ES-Air
TF9BTQL |Clear |JP |Kibana Airlines
T9QK7GX |Clear |IN |Logstash Airways
4AHGESO |Rain |ZA |Kibana Airlines
J684XSR |Sunny |AR |JetBeats
T390OH4 |Cloudy |IN |ES-Air
6. 子查詢
ES SQL 是可以支持類似于 SELECT X FROM (SELECT * FROM Y)
這樣簡單的子查詢的
POST /_sql?format=txt
{"query": "SELECT avg(data.DistanceMiles) from (SELECT FlightNum, OriginWeather, OriginCountry, Carrier, DistanceMiles FROM kibana_sample_data_flights WHERE DestCountry = 'US') as data"
}
其結果如下:
avg(data.DistanceMiles)
-----------------------
4714.944895442431
參考資料
官方文檔:xpack-sql{target=“_blank”}