Elasticsearch7.X的SQL|Elasticsearch7.X的SQL access实现
前言
elasticsearch7.X出来也有一段时间了,正好这次让我给项目中的elasticsearch升级版本,就去了解了一下我需要升级的这块东西。
安装
安装就不多赘述了,我直接在docker上拉的镜像,选择适合自己的方式就行。
SQL access
sql rest api
这次升级也主要是升级这里,系统之前支持通过sql查询elasticsearch,之前系统使用的是elasticsearch_sql来把用户输入的sql转换为elasticsearch的query dsl语句去查询。
可以先去看看官方文档
我们在新版本中弃用es-sql的包,直接使用新版本的sql rest aqi。在项目中引入es的包,通过它给的api去调用es的接口就行了。直接上代码测试
先在es中添加测试数据,可以用postman调用es的rest接口
http://127.0.0.1:9200/_index/_type/_id,如果id存在则是更新
文章图片
image.png
文章图片
测试数据 测试
在代码里我通过restTemplate去请求,来试试简单的查询吧
String elasticsearchAddress = "http://172.19.5.57:9200/_sql?format=json";
JSONObject jsonObject = new JSONObject();
jsonObject.put("query","select name,age from jianshu group by name,age ");
JSONObjectresults = restTemplate.postForObject(elasticsearchAddress,jsonObject,JSONObject.class);
if (jsonObject.get("cursor") == null){
JSONArray columns = results.getJSONArray("columns");
List columnList = JSONArray.parseArray(columns.toJSONString(),Column.class);
JSONArray values = results.getJSONArray("rows");
System.out.println("results:" + results);
List res = JSONArray.parseArray(JSONObject.toJSONString(values),JSONArray.class).stream()
.map(p -> {
JSONObject user = new JSONObject();
for (int i = 0;
i< columnList.size();
i++){
user.fluentPut(columnList.get(i).getName(),p.get(i));
}
return user;
}).collect(Collectors.toList());
System.out.println("res:" + res);
} else {
System.out.println(results);
}
//打印结果
results:{"cursor":"k8OvAwFaAWMBB2ppYW5zaHWYAQEBCWNvbXBvc2l0ZQdncm91cGJ5AAD/AgAHY2ZjYTZmYQEMbmFtZS5rZXl3b3JkAAABAAAACDFhMmY5MTA2AQthZ2Uua2V5d29yZAAAAQAA6AcBCgIHY2ZjYTZmYQAC566A5LmmCDFhMmY5MTA2AAIxMAACAQAAAAABAP////8PAAAAAAAAAAAAAAAAAVoDAAICAAAAAAAA/////w8CAWsHY2ZjYTZmYQAAAWsIMWEyZjkxMDYAAAEDAA==","columns":[{"name":"name","type":"text"},{"name":"age","type":"text"}],"rows":[["","10"]]}
res:[{"name":"","age":"10"}]
@Data
public class Column {private String name;
private String type;
}
从返回结果来看,由于es节约性能。是把行列分开返回的(从官方文档也可以看出来)。所以我们拿到结果后转成我们常见的key,value的形式。
一个小插曲 在正式环境上我处理列数据时
List columnList = JSONObject.parseArray(results.getString("columns"))
.stream()
.map(p -> ((JSONObject) p).getString("name"))
.collect(Collectors.toList());
得到的结果是正确的
文章图片
image.png
但是我在测试代码上那样获取列数据时是这样的,返回来的结果都是一样的,可能是我哪个包的版本不一致。后面再检查下。
文章图片
image.png cursor 从结果看还有另外一个返回值cusor,从官网文档上看到用于大数据的查询(也就是分页),在我们使用分页时可以添加参数
jsonObject.put("fetch_size",5);
特别注意:在分页后,想要查询后面数据时,请求时参数只能有cursor这一个。并且返回来的数据不再有列数据,所以我们在正式使用时需要在分页查询第一次后把列数据保存下来。
如下面官网例子所示
文章图片
image.png
SQL JDBC 最开始我就走偏了,用了这个,结果发现需要es的白金版会员才能使用,所以感觉没啥用,毕竟要花钱。简单实现了一下。
实现
使用jdbc需要先引入x-pack包
org.elasticsearch.plugin
x-pack-sql-jdbc
7.13.0
然后就是关于es操作的service以及对应serviceImpl了,主要就是去实现ElasticsearchRepository以及父类的方法。
public interface UserService {public void saveUser(User user);
public User findUser(Long id);
}
@Service
public class UserServiceImpl implements UserService {@Resource
private UserRepository userRepository;
@Override
public void saveUser(User user) {
userRepository.save(user);
}@Override
public User findUser(Long id) {
return userRepository.findById(id).get();
}
}
public interface UserRepository extends ElasticsearchRepository {
}
@Data
@Accessors(chain = true)
@Document(indexName = "jianshu", type = "author")
public class User implements Serializable {@Id
private Long id;
private String name;
private String age;
}
实现类写好后,咱们就可以简单测试一下
@Test
public void save() {
userService.saveUser(new User()
.setName("jdbc").setAge("11"));
}
文章图片
image.png
@Test
public void findById() {
User byId = userService.findUser(1L);
System.out.println(byId);
}
文章图片
image.png 【Elasticsearch7.X的SQL|Elasticsearch7.X的SQL access实现】这其中也是踩了一些坑的,不过具体久了忘记了.....欢迎留言讨论
推荐阅读
- 热闹中的孤独
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 放屁有这三个特征的,请注意啦!这说明你的身体毒素太多
- 一个人的旅行,三亚
- 布丽吉特,人生绝对的赢家
- 慢慢的美丽
- 尽力
- 一个小故事,我的思考。
- 家乡的那条小河
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量