一、总概
Elasticsearch 在 Basic 授权中支持以 SQL 语句的形式检索文档,SQL 语句在执行时会被翻译为 DSL 执行。从语法的角度来看,Elastisearch 中的 SQL 语句与RDBMS 中的 SQL 语句基本一致, 所以对于有数据库编程基础的人来说大大降低了使用 Elaticsearch 的学习成本。
Elasticsearch 提供了多种执行SQL 语句的方法,可使用类似_search 样的 REST接口执行也可以通过命令行执行。它甚至还提供了 JDBC 和 ODBC 驱动来执行 SQL语句,但 JDBC 和 ODBC需要付费。
二、 sql 接口
在早期版本中,Elasticsearch 执行 SQL 的 REST 接口为_xpack/sql, 但在版本7 以后这个接口已经被废止而推荐使用_sql 接口。例如:
POST _sql?format=txt
{
"query": "select DestCountry, OriginCountry,AvgTicketPrice from kibana_sample_data_flights where Carrier = 'Kibana Airlines' order by AvgTicketPrice desc"
}
在示例中,_sql接口通过query参数接收SQL语句,而SQL语句也包含有select、from、where、 orderby 等子句。_sql 接口的 URL 请求参数 format 定义了返回结果格式。比如在示例中定义了返回结果格式为 txt。除了 txt 以外,_sqI 接口还支持 csv、 json、tsv、yaml 等等格式。
示例中的请求会将所有航空公同为 Kibana Airines 的航班文档检索出来,并以文本表格的形式返回。
对于总量比较大的 SOL 查询,sql 接口还支持以游标的形式实现分页。当_sql接口的请求参数中添加了 fetch_size 参数,sql 接口在返回结来时就会根据fetch_size 参数设置的大小返回相应的条数,并在返回结果中添加游标标识。具体来说,当请求_sql 接口时设置的 forma 为 json 时,返回结果中会包含 cursor属性;而其他情况下则会在响应中添加Cursor报头。例如还是执行示例中的SOL ,但是加入分页支持:
POST _sql?format=json
{"query":"select DestCountry, OriginCountry,AvgTicketPrice from kibana_sample_data_flights where Carrier = 'Kibana Airlines' order by AvgTicketPrice desc",
"fetch_size":10
}
在示例的请求中,为了能够在返回结果中直接看到 cursor 值,我们将 format设置为 json,可以看到:
POST _sql?format=json
{ "cursor":"k8OvAwFaAXN4RkdsdVkyeDFaR1ZmWTI5dWRHVjRkRjkxZFdsa0RY
RjFaWEo1UVc1a1JtVjBZMmdCRkdWV2JWZDNXRWxDTVZKMlowOXpha2R4U0RVM0F
BQUFBQUFCYk5jV1dIZ3daMFZWVld4UlNtbElSVXBTWVdaRFN6RmlVUT09/w8DA
WYLRGVzdENvdW50cnkBC0Rlc3RDb3VudHJ5AQdrZXl3b3JkAQAAAWYNT3JpZ2luQ29
1bnRyeQENT3JpZ2luQ291bnRyeQEHa2V5d29yZAEAAAFmDkF2Z1RpY2tldFByaWNlA
Q5BdmdUaWNrZXRQcmljZQEFZmxvYXQAAAABBw=="
}
在上面的请求中,参数 cursor 就是第一个请求返回结果中的 cursor 值,反复执行请求,Elasticsearch 就会将第一次请求的全部内容以每次 10 个的数量全部迭代出来。在请求完所有数据后,应该使用_sql/close 接口将游标关闭以释放资源。
POST _sql/close
{ "cursor":"k8OvAwFaAXN4RkdsdVkyeDFaR1ZmWTI5dWRHVjRkRjkxZFdsa0RY
RjFaWEo1UVc1a1JtVjBZMmdCRkdWV2JWZDNXRWxDTVZKMlowOXpha2R4U0RVM0F
BQUFBQUFCYk5jV1dIZ3daMFZWVld4UlNtbElSVXBTWVdaRFN6RmlVUT09/w8DA
WYLRGVzdENvdW50cnkBC0Rlc3RDb3VudHJ5AQdrZXl3b3JkAQAAAWYNT3JpZ2luQ29
1bnRyeQENT3JpZ2luQ291bnRyeQEHa2V5d29yZAEAAAFmDkF2Z1RpY2tldFByaWNlA
Q5BdmdUaWNrZXRQcmljZQEFZmxvYXQAAAABBw=="
}
除了 fetch_size 以外还有些可以在_sql 接口请求体中使用的参数,如下:
query 需要执行的 SQL 语句,必须要设置的参数
fetch_size 默认 1000,每次返回的行数
filter 默认 none,使用 DSL 设置过滤器
request_timeout 默认 90s,请求超时时间
page_timeout 默认 45s,分页超时时间
tume_zone 默认 Z,时区
field_multi_value_leniency 默认 false,如果一个字段返回多个值时是否忽略
在这些参数中,fiter 可以使用 DSL 对文档做过滤,支持 DSL 中介绍的所有查询条件。query 中的 SQL 语句在翻译为 DSL 后,会与 filter 中的 DSL 查询语句共同组合到 bool 查询中。其中 SQL 语句生成的 DSL 将出现在 must 子句,而 filter中的 DSL 则出现在 filter 子句中。来想要查看 SQL 语句翻译后的 DSL. 可以使用_sql/translate 执行相同的请求,在返回结果中就可以看到翻译后的 DSL 了。
三、 SQL 语法
Elasticsearch 支持传统关系型数据库 SQL 语句中的查询语句,但并不支持DML、DCL 句。换句话说,它只支持 SELECT 语句,不支持 INSERT、UPDATE、DELETE语句。SELECT 语句以外,Elaticsarch 还支持 DESCRIBE 和 SHOW 语句。
SELECT 语句
SELECT 语句用于查询文档,基本语法格式:
SELECT select _expr,
[ FROM table_name」
[WHERE condtion]
[ GROUP BY grouping_element]
[ HAVING condition J
[ ORDER BY expression [ASC|DESC]
[ LIMIT[ count]]
通过示例可以看出,Elastiesearch 的 SELECT 语句跟普通 SQL 几乎没有什么区别,支持 SELECT、FROM、 WHERE、 GROUP BY、HAVING、 ORDER BY 及 LIMTT子句。
SELECT 子句中可以使用星号或文档字段名称列表,FROM 子句则指定要检索的索引名称,而 WHERE 子句则设定了检索的条件。一般的 SQL 查询使用这三个子句就足够了,而 GROUP BY 和 HAVING 子句则用于分组,ORDER BY 子句用于排序,而 LIMIT 一般则可以用于分页。和传统 SQL 语句非常接近。
DESCRIBE 语句
DESCRIBE 语句用于查看一个索引的基础信息,在返回结果中一般会包含column、type、mapping 三个列,分别对应文档的字段名称、传统数据库类型及文档字段中的类型。例如要查看索引的基本信息:
POST _sql?format=txt
{ "query":"describe kibana_sample_data_flights"
}
SHOW 语句
SHOW 语句包括三种形式,即 SHOW COLUMNS、SHOW FUNCTIONS 和 SHOW TABLES。
SHOW COLUMNS 用于查看一个索引中的字段情况,它的作用与 DESCRIBE 语句完全一样,其至连返回结果都是一样的。
SHOW FUNCTIONS 用于返回在 Elastiesearch SQL 中支持的所有函数,返回结果中包括 MIN、MAX、COUNT 等常用的聚集函数。
SHOW TABLES 用看 Elaticecearch 中所有的索引。
POST _sql?format=txt
{ "query":"show columns in kibana_sample_data_flights"
}
POST _sql?format=txt
{ "query":"show functions"
}
POST _sql?format=txt
{ "query":"show tables"
}
这三种形式都支持使用 LIKE 子句过滤返回结果,LIKE 子句在用法上与 SQL语句中的 LIKE 类似。例如,“show functions like 'a%"将只返回以 a 开头的函数。
四、操作符与函数
Elasticsearch SQL 中支持的操作符与函数有 100 多种,这些操作符大多与普通 SQL 语言一致,所以这里只介绍一些与普通 SQL 语句不一样的地方。
先来看一下比较操作符。一般等于比较在 SQL 中使用等号“=”,这在ElasticsearchSQL 中也成立。但是 Elasticseareh SQL 还引人了另一个等号比较“<= >”,这种等号可以在左值为 null 时不出现异常。
LIKE 操作符,在 LIKE 子句中可以使用%代表任意多个字符,而使用下划线 _ 代表单个字符。Elasticsearch SQL 不仅支持 LIKE 子句,还支持通过 RLIKE 子句以正则表达式的形式做匹配,这大大扩展了 SQL 语句模糊匹配的能力。
尽管使用 LIKE 和 RLIKE 可以实现模糊匹配,但它离全文检索还差得很远。SQL语句的 WHERE 子句一般都是使用字段整体值做比较,而没有使用词项做匹配的能力。为此 Elasticsearch SQL 提供了 MATCH 和 OUERY 两个函数,以实现在 SQL做全文检索。例如在示例 8-33 中的两干请求分别使用 match 和 query 函数,它们的作用都是检索 DestCounty 字段为 CN 的文档:
POST _sql?format=txt
{ "query":"""
select DestCountry, OriginCountry,AvgTicketPrice,score()
from kibana_sample_data_flights
where match(DestCountry,'CN') """
}
POST _sql?format=txt
{ "query":"""
select DestCountry, OriginCountry,AvgTicketPrice,score()
from kibana_sample_data_flights
where query('DestCountry:CN') """
}
在示例中的两个请求的 selet 子句中都使用了 SCORE 函数,它的作用是获取检索的相关度评分值。
Elasticsearch SQL支持传统SQL中的聚集函数,这包括MAX、MIN、AVG、COUNT、SUM 等。同时,它还支持一些 Elasticsearch 特有的聚集函数,这些聚集函数与Elasticsearch 聚集查询相对应。这包括 FIRST/FIRST_VALUE 和 LAST/LAST VALUE, 可用于查看某个字段首个和最后一个非空值; PERCENTILE 和 PERCENTILE RANK 用于百分位聚集,KURTOSIS,SKEWNESS、STDDEV_ POP、SUM OF SQUARES 和 VAR POP 可用于运算其他统计聚集。除了以上这些函数和操作符,Elasticsearch SQL还定义了一组用于日期、数值以及字符串运算的函数。