Springboot操作ElasticSearch方法,RestTemplate在服务器代理后没有端口号情况下操作ElasticSearch

配置ElasticSearch

配置ElasticSearch的目的是为了让Springboot能够访问到ES,从而能够利用springboot发送Http请求,对ES进行相关的增删改查操作。常用的配置操作有RestHighLevelClient和RestTemplate,对于个人主机上的ES,一般使用RestHighLevelClient即可,但是对于使用过代理的服务器(没有端口号),要使用RestTemplate来发送Http请求。

RestHighLevelClient

构建项目时,要选择elasticsearch,这里的构建是从alibaba下载,从spring官方下载界面略有差异,但同样存在非关系型数据库elasticsearch选项
在这里插入图片描述

  1. 导入依赖
		<dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
            <version>7.6.2</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.6.2</version>
            <scope>compile</scope>
        </dependency>

这两个依赖为常用依赖,一般而言导入即可正常使用,但是当代码部署到服务器上时,可能会出现java.lang.NoClassDefFoundError错误,这个是因为缺少了ES的核心依赖,导入即可

<dependency>
  <groupId>org.elasticsearch</groupId>
  <artifactId>elasticsearch</artifactId>
  <version>7.6.2</version>
</dependency>
  1. 编写springboot配置文件
    在resources文件夹下的application.properties文件(yml文件稍稍格式不同)中,编写elasticsearch.url,这样写的目的是防止代码写死,便于以后修改。在RestHighLevelClient可以选择不用,因为配置也是一次即可
spring.application.name=es_control #name一般自动生成
elasticsearch.url=http://127.0.0.1:9200/
  1. 编写ES配置类
package com.gz.es_control.config;

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ElasticSearchClientConfig {
    private String serverAddress;
    @Bean
    public RestHighLevelClient restHighLevelClient(){
        RestHighLevelClient client=new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("127.0.0.1",9200,"http")
                )
        );
        return client;
    }
}

这样,在@Bean注解下,返回的client将会自动生成Bean,注入到spring容器中(名字为restHighLevelClient)。
当然,可以选择多写一些其他信息,比如请求获取数据的超时时间等,个人学习不需要配置过多,详细配置也可查阅资料。
4. restHighLevelClient使用
编写controller层接口(仅写部分接口,其他接口大同小异)

添加依赖

		<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.33</version>
        </dependency>

在controlller层代码中,import com.alibaba.fastjson.JSONObject;
注意不要选到其他的JSON类,可能导致无法接收到请求体的JSON数据

package com.example.demo.controller;

import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;

@RestController
@RequestMapping(value = "/")
public class ESController {
    @Autowired
    RestHighLevelClient restHighLevelClient;

    //查询索引是否存在
    @GetMapping(value = "/query/{indexName}")
    public String existIndex(@PathVariable(name = "indexName")String  indexName) throws IOException {
        GetIndexRequest getIndexRequest = new GetIndexRequest(indexName);
        boolean exists = restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
        if (!exists){
            return "Index does not exist";
        }else {
            return "Index exist";
        }
    }

	//创建索引
    @PostMapping(value = "/create/{indexName}")
    @ResponseBody
    public CreateIndexResponse createIndex(@PathVariable(name = "indexName")String indexName,@RequestBody JSONObject jsonParam ) throws  IOException {
        CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName);
        createIndexRequest.mapping(jsonParam.getJSONObject("mappings"));
        System.out.println(jsonParam);//同样的方法,可以设置setting值,来决定集群分片数等
        CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
        return createIndexResponse;
    }

	//删除索引
    @DeleteMapping(value = "/delete/{indexName}")
    public boolean deleteIndex(@PathVariable(name = "indexName")String indexName) throws IOException {
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(indexName);
        AcknowledgedResponse delete = restHighLevelClient.indices().delete(deleteIndexRequest,RequestOptions.DEFAULT);
        boolean acknowledged = delete.isAcknowledged();
        return acknowledged;
    }
}

查询和删除比较直接,来测试一下创建索引,看看ES中的mapping结构是否和传的值一样
使用postman发送请求,可以得到回应
在这里插入图片描述
使用elasticsearch-head-master查看
在这里插入图片描述
可以看到,ES中的索引mappings值确实和请求体一致

RestTemplate

前面提到,RestHighLevelClient和RestTemplate都能对ES进行操作,但是如果我们要对服务器的ES,而服务器又进行了代理,没有端口号,如http://111.111.111.111/es/为服务器es地址,那么这个时候RestHighLevelClient可能没有那么好操作。
RestTemlate可以解决和简化这个问题

创建Service层代码

package com.example.demo.service;

import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;

@Service
public class IndexService {
    @Value("${elasticsearch.rul}")
    private String serverAddress;//这里用到了开头说的配置

    //创建索引
    public String createIndex(JSONObject jsonParam, String metadataName) throws IOException {
        RestTemplate restTemplate=new RestTemplate();
        boolean exists;
        try {
            restTemplate.getForObject(serverAddress+metadataName,Object.class);
            exists=true;
        }catch (Exception e){ exists=false; }
        if(exists){
            return "索引已存在,创建失败";
        }
        String url=serverAddress+metadataName;
        restTemplate.put(url,jsonParam);
        return "索引创建成功";
    }

    //删除索引
    public String deleteIndex(String metadataName) throws IOException {
        RestTemplate restTemplate=new RestTemplate();
        boolean exists;
        try {
            restTemplate.getForObject(serverAddress+metadataName,Object.class);
            exists=true;
        }catch (Exception e){ exists=false; }
        if(exists){
            String url=serverAddress+metadataName;
            restTemplate.delete(url);
            return "删除索引成功";
        }else{
            return "索引不存在,删除失败";
        }
    }

    //重索引
    private void reindex(String oldIndex,String newIndex){
        String url=serverAddress+"_reindex";
        String str="{\n" +
                "    \"source\": {\n" +
                "    \"index\": \""+oldIndex+"\"\n" +
                "  },\n" +
                "  \"dest\": {\n" +
                "    \"index\": \""+newIndex+"\"\n" +
                "  }\n" +
                "}";
        JSONObject jsonObject=JSONObject.parseObject(str);
        RestTemplate restTemplate=new RestTemplate();
        restTemplate.postForObject(url,jsonObject,JSONObject.class);
    }

    //起别名
    private void realiases(String index,String oldIndex,String newIndex){
        String url=serverAddress+"_aliases";
        String str="{\n" +
                "  \"actions\": [{\"add\": {\n" +
                "    \"index\": \""+newIndex+"\",\n" +
                "    \"alias\": \""+index+"\"\n" +
                "  }}, {\"remove\": {\n" +
                "    \"index\": \""+oldIndex+"\",\n" +
                "    \"alias\": \""+index+"\"\n" +
                "  }}]\n" +
                "}";
        JSONObject jsonObject=JSONObject.parseObject(str);
        RestTemplate restTemplate=new RestTemplate();
        restTemplate.postForObject(url,jsonObject,JSONObject.class);
    }

    //修改索引结构
    public void modifyIndex(JSONObject jsonObject_mappings,String metadataName) throws IOException {
        RestTemplate restTemplate=new RestTemplate();
        boolean exists;
        try {
            restTemplate.getForObject(serverAddress+metadataName,Object.class);
            exists=true;
        }catch (Exception e){ exists=false; }
        if (exists) {
            createIndex(jsonObject_mappings, metadataName + "_es");
            reindex(metadataName, metadataName + "_es");
            deleteIndex(metadataName);
            
			Thread.sleep(1000);//线程休眠一秒,防止数据丢失
			
            createIndex(jsonObject_mappings, metadataName);
            reindex(metadataName + "_es", metadataName);
            deleteIndex(metadataName + "_es");
        }else{
            createIndex(jsonObject_mappings,metadataName);
        }
    }
}

elasticsearch两次reindex的时间间隔要大于一秒,否则可能数据丢失,所以这里Thread.sleep(1000);
Service层代码的目的是为了创建一个Bean,供Controller层代码使用。
编写Controller层代码
因为实现功能的代码都在IndexService中,所以这里Controller层代码比较简单,如果要实现其他功能,可以创建相应的Service的Bean,在Controller层调用

package com.example.demo.controller;

import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.example.demo.service.*;

import java.io.IOException;

@RestController
@RequestMapping(value = "/")
public class ESControllerRestTemplate {
    @Autowired
    private IndexService indexService;

    @PostMapping(value = "/createIndexRestTemplate/{indexName}")
    @ResponseBody
    public String createIndex(@PathVariable(name = "indexName")String indexName , @RequestBody JSONObject jsonParam) throws IOException {
        indexService.createIndex(jsonParam,indexName);
        return "success";
    }

    @DeleteMapping(value = "/deleteIndexRestTemplate/{indexName}")
    @ResponseBody
    public String deleteIndex(@PathVariable(name = "indexName")String indexName) throws IOException {
        indexService.deleteIndex(indexName);
        return "success";
    }

    @PutMapping(value = "/modifyIndexRestTemplate/{indexName}")
    @ResponseBody
    public String modifyIndex(@PathVariable(name = "indexName")String indexName,@RequestBody JSONObject jsonParam) throws IOException {
        indexService.modifyIndex(jsonParam,indexName);
        return "success";
    }
}

创建和删除等的功能跟RestHighLevelClient相同,可以实现创建索引、删除索引等。
这里测试修改索引的功能,ES建立索引后,mappings结构不能修改,但是ES提供了另外一个功能reindex,类似于删除并且重新创建索引(用新的mappings),同时将原来索引的数据迁移到新的索引中,保证数据不会丢失。
先看看索引中的结构和数据
在这里插入图片描述

在这里插入图片描述
然后调用/modifyIndexRestTemplate/tryagain接口
在这里插入图片描述
可以看到修改索引结构成功,再看看ES现在的结构
在这里插入图片描述
可以看到索引的结构已经改变,再看看数据
在这里插入图片描述
可以看到数据也没有丢失(因为所有数据都没有包含新字段的信息,所以新字段不显示,但是可以在mappings中看到结构已经修改,包含了新加的字段)。

同样可以利用RestTemplate实现增删改查、起别名等相关的ES操作,操作方法大同小异。

总结

RestHighLevelClient和RestTemplate都能对ES进行操作,RestTemplate的好处是可以解决当服务器的ES进行代理之后没有端口的情况,并且RestTemplate对ES的操作方法基本一致,没有过多的变化,可以结合前端传来的JSON数据,灵活性高,但用RestTemplate发送Http请求时要处理好JSON数据,保证请求体的正确性。
如果要简化前端的操作,不想前端书写完整的JSON数据,可以在springboot代码中编写部分JSON形式的String,前端传入对应的数据后,拼接成完整的JSON形式的String变量,然后利用

JSONObject jsonObject=JSONObject.parseObject(str);

将其转换为JSONObject,用于RestTemplate的请求体中。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Spring Boot是一个开箱即用的框架,可以简化Java应用程序的开发。而Elasticsearch是一个开源的搜索引擎,具有强大的全文搜索和分析能力。 要在Spring Boot操作Elasticsearch,首先需要在项目的依赖管理中增加Elasticsearch的相关依赖,例如elasticsearchspring-boot-starter-data-elasticsearch。 在配置文件(application.properties或application.yml)中,需要设置Elasticsearch的连接信息,如主机名、端口号和索引名称等。可以通过spring.data.elasticsearch.cluster-nodes和spring.data.elasticsearch.cluster-name属性来进行配置。 接下来,在Java代码中,可以使用Spring Data Elasticsearch提供的API来进行操作。可以通过注解方式定义实体类和索引,使用ElasticsearchRepository来实现数据的增删改查操作。 通过ElasticsearchRepository的save方法可以将数据保存到Elasticsearch中。通过findById方法可以根据ID查询数据,通过search方法可以进行全文搜索等。 在使用Elasticsearch的时候,还可以进行索引的创建和删除操作。可以使用IndicesAdminClient提供的API来调用创建和删除索引的操作。 此外,Elasticsearch还提供了丰富的搜索功能,如分页查询、排序查询、聚合查询等。可以通过QueryBuilder和SearchRequestBuilder等类来构建复杂的查询语句。 总之,Spring BootElasticsearch的结合可以提供一个简便而强大的搜索引擎应用程序开发框架。开发人员可以通过简单的配置和API调用来实现数据的存储、检索和分析功能,大大简化了开发过程。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值