出自 图灵学院 ElasticSearch课程
我自己学完了,然后给老师的代码和讲义自己练习了一遍,然后整理了一下,做了个笔记
概述
Elasticsearch SQL允许执行类SQL的查询,可以使用REST接口、命令行或者是JDBC,都可以使用SQL来进行数据的检索和数据的聚合。
Elasticsearch SQL特点:
本地集成
Elasticsearch SQL是专门为Elasticsearch构建的。每个SQL查询都根据底层存储对相关节点有效执行。
没有额外的要求
不依赖其他的硬件、进程、运行时库,Elasticsearch SQL可以直接运行在Elasticsearch集群上
轻量且高效
像SQL那样简洁、高效地完成查询
SQL与Elasticsearch对应关系
| SQL | Elasticsearch |
|---|---|
| column(列) | field(字段) |
| row(行) | document(文档) |
| table(表) | index(索引) |
| schema(模式) | mapping(映射) |
| database server(数据库服务器) | Elasticsearch集群实例 |
Elasticsearch 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 ] [, ...] ) ) ]
目前FROM只支持单表
Elasticsearch SQL目前的一些限制
目前Elasticsearch SQL还存在一些限制。例如:不支持JOIN、不支持较复杂的子查询。所以,有一些相对复杂一些的功能,还得借助于DSL方式来实现。
另外现在ElasticSearch中 还是dsl语句是主流语句,sql语句在ElasticSearch中不是那么的成熟.
案例
查询职位索引库中的一条数据
format:表示指定返回的数据类型
//1.查询职位信息
GET /_sql{"query":"SELECT * FROM es_db limit 1"}
结果
{"columns" : [{"name" : "address","type" : "text"},{"name" : "age","type" : "long"},{"name" : "city","type" : "text"},{"name" : "name","type" : "text"},{"name" : "provice","type" : "text"},{"name" : "remark","type" : "text"},{"name" : "sex","type" : "long"},{"name" : "street","type" : "text"}],"rows" : [["广州荔湾大厦",28,null,"李四",null,"java assistant",1,null]]}
结果返回表的格式
默认是返回json格式的结果
GET /_sql?format=txt{"query":"SELECT * FROM es_db limit 1"}
结果
address | age | city | name | provice | remark | sex | street---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------广州荔湾大厦 |28 |null |李四 |null |java assistant |1 |null
除了txt类型,Elasticsearch SQL还支持以下类型,
| 格式 | 描述 |
|---|---|
| csv | 逗号分隔符 |
| json | JSON格式 |
| tsv | 制表符分隔符 |
| txt | 类cli表示 |
| yaml | YAML人类可读的格式 |
使用tsv格式
GET /_sql?format=tsv{"query":"SELECT * FROM es_db limit 1"}
结果
address age city name provice remark sex street广州荔湾大厦 28 李四 java assistant 1
将SQL转换为DSL
将sql转成dsl语句, 这种使用场景是:比如说你MySQL用的非常的6 ,但是你不太会ElasticSearch的dsl语法,那么就可以把你想查询的效果用sql语句写出来,然后再翻译成dsl语句.
输入:
GET /_sql/translate{"query":"SELECT * FROM es_db where address = '广州荔湾大厦'"}
结果:
{"size" : 1000,"query" : {"term" : {"address.keyword" : {"value" : "广州荔湾大厦","boost" : 1.0}}},"_source" : {"includes" : ["address","age","city","name","provice","remark","sex","street"],"excludes" : [ ]},"sort" : [{"_doc" : {"order" : "asc"}}]}
然后你把翻译的语句跟上 dsl语句的请求地址 比如说: GET /es_db/_search ,这样就可以使用了.
GET /es_db/_search{"size" : 1000,"query" : {"term" : {"address.keyword" : {"value" : "广州荔湾大厦","boost" : 1.0}}},"_source" : {"includes" : ["address","age","city","name","provice","remark","sex","street"],"excludes" : [ ]},"sort" : [{"_doc" : {"order" : "asc"}}]}
职位全文检索
检索address包含广州和name中包含张三的用户。
在执行全文检索时,需要使用到MATCH函数。
MATCH(field_exp,constant_exp[, options])
field_exp:匹配字段
constant_exp:匹配常量表达式
用sql语句可以这么写:
GET /_sql?format=txt{"query":"select * from es_db where MATCH(address, '广州') or MATCH(name, '张三') limit 10"}
结果:
address | age | city | name | provice | remark | sex | street---------------+---------------+---------------+---------------+---------------+---------------+---------------+---------------广州荔湾大厦 |28 |null |李四 |null |java assistant |1 |null广州白云山公园 |26 |null |rod |null |php developer |0 |null
通过Elasticsearch SQL方式实现分组统计
输入:
GET /_sql?format=txt{"query":"select age, count(*) as age_cnt from es_db group by age"}
结果:
age | age_cnt---------------+---------------19 |122 |125 |126 |128 |1
这种方式要更加直观、简洁。
