Elasticsearch7.X的SQL access實(shí)現(xiàn)

前言

elasticsearch7.X出來(lái)也有一段時(shí)間了,正好這次讓我給項(xiàng)目中的elasticsearch升級(jí)版本,就去了解了一下我需要升級(jí)的這塊東西。

安裝

docker pull elasticsearch:7.7.0
docker run --name elasticsearch -d -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -e "discovery.type=single-node" -p 9200:9200 -p 9300:9300 elasticsearch:7.7.0
看到這個(gè)就說(shuō)明裝好了

image.png

可以參考docker部署運(yùn)行ES

SQL access

sql rest api

這次升級(jí)也主要是升級(jí)這里,系統(tǒng)之前支持通過(guò)sql查詢elasticsearch,之前系統(tǒng)使用的是elasticsearch_sql來(lái)把用戶輸入的sql轉(zhuǎn)換為elasticsearch的query dsl語(yǔ)句去查詢。
可以先去看看官方文檔
我們?cè)谛掳姹局袟売胑s-sql的包,直接使用新版本的sql rest aqi。在項(xiàng)目中引入es的包,通過(guò)它給的api去調(diào)用es的接口就行了。直接上代碼測(cè)試
先在es中添加測(cè)試數(shù)據(jù),可以用postman調(diào)用es的rest接口
http://127.0.0.1:9200/_index/_type/_id,如果id存在則是更新

image.png

測(cè)試數(shù)據(jù)

測(cè)試

在代碼里我通過(guò)restTemplate去請(qǐng)求,來(lái)試試簡(jiǎn)單的查詢吧

        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 ");
        JSONObject  results = restTemplate.postForObject(elasticsearchAddress,jsonObject,JSONObject.class);
        if (jsonObject.get("cursor") == null){
            JSONArray columns = results.getJSONArray("columns");
            List<Column> columnList = JSONArray.parseArray(columns.toJSONString(),Column.class);
            JSONArray values = results.getJSONArray("rows");
            System.out.println("results:" + results);
            List<JSONObject> 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);
        }
//打印結(jié)果
results:{"cursor":"k8OvAwFaAWMBB2ppYW5zaHWYAQEBCWNvbXBvc2l0ZQdncm91cGJ5AAD/AgAHY2ZjYTZmYQEMbmFtZS5rZXl3b3JkAAABAAAACDFhMmY5MTA2AQthZ2Uua2V5d29yZAAAAQAA6AcBCgIHY2ZjYTZmYQAC566A5LmmCDFhMmY5MTA2AAIxMAACAQAAAAABAP////8PAAAAAAAAAAAAAAAAAVoDAAICAAAAAAAA/////w8CAWsHY2ZjYTZmYQAAAWsIMWEyZjkxMDYAAAEDAA==","columns":[{"name":"name","type":"text"},{"name":"age","type":"text"}],"rows":[["簡(jiǎn)書","10"]]}
res:[{"name":"簡(jiǎn)書","age":"10"}]
@Data
public class Column {

    private String name;

    private String type;
}

從返回結(jié)果來(lái)看,由于es節(jié)約性能。是把行列分開返回的(從官方文檔也可以看出來(lái))。所以我們拿到結(jié)果后轉(zhuǎn)成我們常見(jiàn)的key,value的形式。

一個(gè)小插曲

在正式環(huán)境上我處理列數(shù)據(jù)時(shí)

List<String> columnList = JSONObject.parseArray(results.getString("columns"))
                .stream()
                .map(p -> ((JSONObject) p).getString("name"))
                .collect(Collectors.toList());

得到的結(jié)果是正確的


image.png

但是我在測(cè)試代碼上那樣獲取列數(shù)據(jù)時(shí)是這樣的,返回來(lái)的結(jié)果都是一樣的,可能是我哪個(gè)包的版本不一致。后面再檢查下。


image.png

cursor

從結(jié)果看還有另外一個(gè)返回值cusor,從官網(wǎng)文檔上看到用于大數(shù)據(jù)的查詢(也就是分頁(yè)),在我們使用分頁(yè)時(shí)可以添加參數(shù) jsonObject.put("fetch_size",5);
特別注意:在分頁(yè)后,想要查詢后面數(shù)據(jù)時(shí),請(qǐng)求時(shí)參數(shù)只能有cursor這一個(gè)。并且返回來(lái)的數(shù)據(jù)不再有列數(shù)據(jù),所以我們?cè)谡绞褂脮r(shí)需要在分頁(yè)查詢第一次后把列數(shù)據(jù)保存下來(lái)。
如下面官網(wǎng)例子所示

image.png

SQL JDBC

最開始我就走偏了,用了這個(gè),結(jié)果發(fā)現(xiàn)需要es的白金版會(huì)員才能使用,所以感覺(jué)沒(méi)啥用,畢竟要花錢。簡(jiǎn)單實(shí)現(xiàn)了一下。

實(shí)現(xiàn)

使用jdbc需要先引入x-pack包

<dependency>
  <groupId>org.elasticsearch.plugin</groupId>
  <artifactId>x-pack-sql-jdbc</artifactId>
  <version>7.13.0</version>
</dependency>

然后就是關(guān)于es操作的service以及對(duì)應(yīng)serviceImpl了,主要就是去實(shí)現(xiàn)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<User, Long> {
}
@Data
@Accessors(chain = true)
@Document(indexName = "jianshu", type = "author")
public class User implements Serializable {

    @Id
    private Long id;

    private String name;

    private String age;
}

實(shí)現(xiàn)類寫好后,咱們就可以簡(jiǎn)單測(cè)試一下

@Test
    public void save() {
        userService.saveUser(new User()
                .setName("簡(jiǎn)書jdbc").setAge("11"));
    }
image.png
 @Test
    public void findById() {
        User byId = userService.findUser(1L);
        System.out.println(byId);
    }
image.png

這其中也是踩了一些坑的,不過(guò)具體久了忘記了.....歡迎留言討論

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容