[TOC]
我们知道ElasticSearch提供的功能是相当多且复杂的,学习曲线陡峭。对于没有接触过Elastic的技术同学来说,学习周期和难度是较大的,而我们只需要满足最基本的查询就OK啦,没必要整那些没用的。千呼万唤始出来,在ElasticSearch6.3.0版本开始,在广大ES粉丝的强烈要求下,Elastic终于支持SQL查询了。虽然SQL查询功能很弱,但聊胜于无。SQL查询功能的提供,极大的方便了Elastic用户。因为不懂SQL的程序员,绝对不能算一个合格的程序员。如果您承认您是一个程序员,我相信你肯定熟悉SQL语句,至少select语句是没有问题的。所以该功能的提供对应Elastic的推广和运用会起到非常积极的作用。
下面,我们演示一下怎么来使用该通用模板的“执行SQL语句”接入点。在举例之前,您可以先了解一下elastic的SQL官方文档:
https://www.elastic.co/guide/en/elasticsearch/reference/current/xpack-sql.html
紧接着2.5中的数据,我们写一个查询语句,需要满足以下要求:查询年纪不小于22岁(已经走上社会的人),姓王的,爱好音乐(sing、music、piano)的人。满足这个要求的SQL语句怎么写呢?大家一起来看一下如下的语句:
```sql
select * from common_index where name like '%王%' and age>=22 and (hobbies like '%sing%' or hobbies like '%music%' or hobbies like '%piano%' ) order by age desc
```
根据以上SQL,java的操作代码:
```java
String sql = "select * from common_index where name like '%王%' and age>=22 "
+ "and (hobbies like '%sing%' or hobbies like '%music%' or hobbies like '%piano%' ) "
+ "order by age desc";
String res=new ShowApiRequest("http://route.showapi.com/2161-5","my_appId","my_appSecret")
.addTextPara("sql",sql)
.post();
System.out.println(res);
```
返回的结果:
```css
{
"showapi_res_error": "",
"showapi_res_code": 0,
"showapi_res_id": "3490bcf174624ab78fdd4aaa957e69f6",
"showapi_res_body": {
"ret_code": 0,
"remark": "操作已执行,结果请参考返回信息。",
"columns": [
{
"name": "age",
"type": "long"
},
{
"name": "hobbies",
"type": "text"
},
{
"name": "id_card",
"type": "text"
},
{
"name": "name",
"type": "text"
}
],
"rows": [
[
28,
"football piano Kongfu",
null,
"王五"
]
]
}
}
```
我还以为返回的结果会是"隔壁老王"了,回看了下原始记录,原来他不懂音乐(^_^)!
在我们返回的记录中,发现有个为null数据,是因为有个字段id_card被用来作为_id使用了,也就是说id_card已经作为了整条记录的唯一标识,在这条记录中已经把id_card数据移除了,但字段还在,所以此处才出现了null的数据。注意观察columns信息中有id_card的信息。
重要的事情差点忘记说明了,select语句的格式:
select [columns | *] from [index_name] where [column] [like / = / <> / > ...] value order by [column] [asc | desc]
以上事例演示的是一条完整的sql语句查询,如果还有附带条件,那就只能使用一段Json结构的语句来操作了,比如查询年龄大于20岁,每次最多返回2条数据,并且支持分页查询。
elastic原始的操作方式:
POST /_sql?format=json
```css
{
"query": "SELECT name,age,hobbies FROM common_index where age>20 ORDER BY age DESC",
"fetch_size": 2,
"columnar": true
}
```
我们的接口操作的方式(java代码):
```java
String sql = "{"
+ " \"query\": \"SELECT name,age,hobbies FROM common_index where age>20 ORDER BY age DESC\",\n" +
" \"fetch_size\": 2,\n" +
" \"columnar\": true\n" +
"}";
String res=new ShowApiRequest("http://route.showapi.com/2161-5","my_appId","my_appSecret")
.addTextPara("sql",sql)
.post();
System.out.println(res);
```
接口返回的数据:
```css
{
"showapi_res_error": "",
"showapi_res_code": 0,
"showapi_res_id": "19d219e950f84a74899e8efaa7269a29",
"showapi_res_body": {
"ret_code": 0,
"values": [
[
"隔壁老王",
"王五"
],
[
36,
28
],
[
"football book calligraphy chess stocks",
"football piano Kongfu"
]
],
"cursor": "q9qtAwFaAXNARFhGMVpYSjVRVzVrUm1WMFkyZ0JBQUFBQUFBQUFFZ1diVFE1ZFV4RGRVbFJXR2xOY0hKamNucHZjRWRSUVE9Pf////8PAwFmBG5hbWUBBG5hbWUBBHRleHQAAAABZgNhZ2UBA2FnZQEEbG9uZwAAAAFmB2hvYmJpZXMBB2hvYmJpZXMBBHRleHQAAAABBw==",
"remark": "操作已执行,结果请参考返回信息。",
"columns": [
{
"name": "name",
"type": "text"
},
{
"name": "age",
"type": "long"
},
{
"name": "hobbies",
"type": "text"
}
]
}
}
```
既然是分页查询,那第二次查询就需要用到cursor参数了:
```css
POST /_sql?format=json
{"cursor": "q9qtAwFaAXNARFhGMVpYSjVRVzVrUm1WMFkyZ0JBQUFBQUFBQUFFZ1diVFE1ZFV4RGRVbFJXR2xOY0hKamNucHZjRWRSUVE9Pf////8PAwFmBG5hbWUBBG5hbWUBBHRleHQAAAABZgNhZ2UBA2FnZQEEbG9uZwAAAAFmB2hvYmJpZXMBB2hvYmJpZXMBBHRleHQAAAABBw==",
"columnar": true
}
```
注意:cursor值是有时效性的,默认时间是1分钟.也就是说超过1分钟后cursor值就失效了.
通过接口,执行以上sql的返回值:
```css
{
"showapi_res_error": "",
"showapi_res_code": 0,
"showapi_res_id": "d89533ff40fd4a1b878133fbe090a4fb",
"showapi_res_body": {
"ret_code": 0,
"values": [
[
"张三",
"李四"
],
[
23,
21
],
[
"football book",
"art music football"
]
],
"cursor": "q9qtAwFaAXNARFhGMVpYSjVRVzVrUm1WMFkyZ0JBQUFBQUFBQUFFa1diVFE1ZFV4RGRVbFJXR2xOY0hKamNucHZjRWRSUVE9Pf////8PAwFmBG5hbWUBBG5hbWUBBHRleHQAAAABZgNhZ2UBA2FnZQEEbG9uZwAAAAFmB2hvYmJpZXMBB2hvYmJpZXMBBHRleHQAAAABBw==",
"remark": "操作已执行,结果请参考返回信息。"
}
}
```