【SpringBoot】整合Elasticsearch 快速入门操作索引

news/2025/1/15 15:34:36/

官网操作文档:Elasticsearch Clients | Elastic      

         踩坑太多了。。。这里表明一下Spring Boot2.4以上版本可能会出现问题,所以我降到了2.2.1.RELEASE。对于现在2023年6月而言,Es版本已经到了8.8,而SpringBoot版本已经到了3.x版本。如果是高版本的Boot在配置类的时候会发现RestHighLevelClient已过时。从官网也可以看的出来RestHighLevelClient已过时。所以这篇博文中不会用到关于RestHighLevelClient的Api。

        此篇博文的对应版本关系:Elasticsearch 8.2.0 + Spring Boot 2.7.5。在进入到下面的案例,我需要在这之前先介绍RestClient、RestHighLevelClient、RestClientTransport、ElasticsearchClient。

RestClient

        这个类主要是用作于与服务端IP以及端口的配置,在其的builder()方法可以设置登陆权限的账号密码、连接时长等等。总而言之就是服务端配置

RestClientTransport

        这是Jackson映射器创建传输。建立客户端与服务端之间的连接传输数据。这是在创建ElasticsearchClient需要的参数,而创建RestClientTransport就需要上面创建的RestClient。

ElasticsearchClient

        这个就是Elasticsearch的客户端。调用Elasticsearch语法所用到的类,其就需要传入上面介绍的RestClientTransport。

引入依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<!-- 高版本还需引入此依赖 -->
<dependency><groupId>jakarta.json</groupId><artifactId>jakarta.json-api</artifactId><version>2.0.0</version>
</dependency>

修改yml

        需要注意的是账号和密码可以不需要,看自己的Elasticsearch是否有配置账号密码。具体对Elasticsearch的登陆操作可以看:中偏下的位置就是对账号密码的设置。【Linux】Docker部署镜像环境 (持续更新ing)_小白的救赎的博客-CSDN博客

server:port: 8080elasticsearch:hostAndPort: 192.168.217.128:9200 # 低版本使用的ip: 192.168.217.128port: 9200username: elasticpassword: 123456connectionTimeout: 1000socketTimeout: 30000

配置类    

        这里演示两种情况的配置:第一个代码块是SpringBoot2.4以下 + 7.x版本Elasticsearch的配置。第二个代码块是Spring2.4以上 + 8.x版本Elasticsearch的配置。

@Configuration
public class ElasticConfig extends AbstractElasticsearchConfiguration {@Value("${elasticsearch.hostAndPort}")private String hostAndPort;@Value("${elasticsearch.username}")private String username;@Value("${elasticsearch.password}")private String password;@Value("${elasticsearch.connectionTimeout}")private String connectTimeout;@Value("${elasticsearch.socketTimeout}")private String socketTimeout;/*** create Elasticsearch client* @return RestHighLevelClient*/@Beanpublic RestHighLevelClient elasticsearchClient() {final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();credentialsProvider.setCredentials(AuthScope.ANY,new UsernamePasswordCredentials(username, password));ClientConfiguration clientConfiguration = ClientConfiguration.builder().connectedTo(hostAndPort).withConnectTimeout(Long.parseLong(connectTimeout)).withSocketTimeout(Long.parseLong(socketTimeout)).withBasicAuth(username, password).build();return RestClients.create(clientConfiguration).rest();}/*** 将连接传入 Elasticsearch在 Spring Boot的模板类中* @return 返回 Es的模板类*/@Beanpublic ElasticsearchRestTemplate elasticsearchRestTemplate() {return new ElasticsearchRestTemplate(elasticsearchClient());}
}
@Configuration
public class ElasticConfig {@Value("${elasticsearch.ip}")private String ip;@Value("${elasticsearch.port}")private String port;@Value("${elasticsearch.username}")private String username;@Value("${elasticsearch.password}")private String password;@Value("${elasticsearch.connectionTimeout}")private String connectTimeout;@Value("${elasticsearch.socketTimeout}")private String socketTimeout;/*** create Elasticsearch client* @return RestHighLevelClient*/@Beanpublic ElasticsearchClient elasticsearchClient() {final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();credentialsProvider.setCredentials(AuthScope.ANY,new UsernamePasswordCredentials(username, password));RestClient restClient = RestClient.builder(new HttpHost(ip, Integer.parseInt(port))).setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider)).setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {@Overridepublic RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder builder) {return builder.setConnectTimeout(Integer.parseInt(connectTimeout)).setSocketTimeout(Integer.parseInt(socketTimeout));}}).build();ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());return new ElasticsearchClient(transport);}
}

控制层

        这里为了方便快速入门,就把所有业务代码都放在控制层中了。这篇博文主要是对索引进行操作,所以说获取到ElasticsearchClient后会调用indices()方法,这个方法就是操作索引的方法。次代码块是展示变量以及类注解。后面逐一暂时各个测试代码块Api以及返回结果。

@RestController
@RequestMapping("/es")
@Slf4j
public class EsController{@Autowiredprivate ElasticConfig elasticConfig;
}

创建索引

/*** create index* @return is success?*/
@PutMapping("/createIndex")
public boolean createIndex() throws IOException {CreateIndexRequest indexRequest = new CreateIndexRequest.Builder().index("user").build();CreateIndexResponse indexResponse = elasticConfig.esClient().indices().create(indexRequest);boolean isSuccess = indexResponse.acknowledged();if(isSuccess) {log.info("创建索引成功");} else {log.info("创建索引失败");}return isSuccess;
}

查询单个索引数据

/*** get one index data by id*/
@GetMapping("/getIndex")
public void getIndex() throws IOException {GetResponse<User> response = elasticConfig.esClient().get(g -> g.index("user").id("1000"),User.class);if(response.found()) {log.info("此用户的姓名为,{}",response.source().getUsername());} else {log.info("未查询到此用户");}
}

删除索引

        这里我测试删除索引成功后又把索引添加了回去。为了后面的其它操作做准备。

/*** delete one index*/
@DeleteMapping("/deleteIndex")
public boolean deleteIndex() throws IOException {DeleteIndexRequest indexRequest = new DeleteIndexRequest.Builder().index("user").build();DeleteIndexResponse deleteResponse = elasticConfig.esClient().indices().delete(indexRequest);boolean isSuccess = deleteResponse.acknowledged();if(isSuccess) {log.info("删除索引成功");} else {log.info("删除索引失败");}return isSuccess;
}

增加索引内容

        这里我新增了个实体类,方便添加到索引内容中。这里大概有四种方式可以创建,这里我演示了三种方式,第四种是使用到了ElasticsearchAsyncClient ,这是Elastic异步客户端。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {private String username;private String sex;private Integer age;
}
/*** 向索引内容插入数据*/
@PostMapping("/insertIndexData")
public void insertIndexData() throws IOException {User user = new User("zhangSan","男",18);/*第一种方式:使用DSL语法创建对象IndexRequest<User> indexRequest = IndexRequest.of(i -> i.index("user").id("1000").document(user)IndexResponse indexResponse = elasticConfig.esClient().index(indexRequest.build()););*//*第二种方式:使用Elasticsearch客户端上配置的对象映射器映射到JSON。IndexResponse indexResponse = elasticConfig.esClient().index(i -> i.index("user").id("1000").document(user));*/// 第三种方式:使用构造器模式IndexRequest.Builder<User> indexRequest = new IndexRequest.Builder<>();indexRequest.index("user");indexRequest.id("1000");indexRequest.document(user);IndexResponse indexResponse = elasticConfig.esClient().index(indexRequest.build());log.info("index,{}",indexResponse.index());log.info("id,{}",indexResponse.id());log.info("version,{}",indexResponse.version());
}

批量添加索引数据

        BulkRequest包含一组操作,每个操作都是具有多个变体的类型。为了创建这个请求,可以方便地将构建器对象用于主请求,并将流利的DSL用于每个操作。下面的示例显示了如何为列表或应用程序对象编制索引。

        operations是BulkOperation的生成器,BulkOperation是一种变体类型。此类型具有索引创建更新删除变体。

/*** 批量插入索引数据*/
@PostMapping("/batchInsertIndex")
public void batchInsertIndex() throws IOException {// 将需要批量添加的数据放到List中List<User> list = new ArrayList<>();list.add(new User("liSi","女",20));list.add(new User("wangWu","男",22));// 使用BulkRequest的构造器BulkRequest.Builder request = new BulkRequest.Builder();for(User user : list) {request.operations(l -> l.index(i -> i.index("user").document(user)));}BulkResponse response = elasticConfig.esClient().bulk(request.build());if(response.errors()) {log.info("批量插入报错");} else {log.info("批量插入成功");}
}

批量删除索引数据

/*** 批量删除索引数据*/
@DeleteMapping("/batchDeleteIndex")
public void batchDeleteIndex() throws IOException {BulkRequest.Builder request = new BulkRequest.Builder();// 根据id做到删除索引的数据request.operations(l -> l.delete(i -> i.index("user").id("vGK5sogBM87kk5Mw8V0P")));request.operations(l -> l.delete(i -> i.index("user").id("u2K5sogBM87kk5Mw8V0P")));BulkResponse response = elasticConfig.esClient().bulk(request.build());if(response.errors()) {log.info("批量删除报错");} else {log.info("批量删除成功");}
}

          这里批量删除接口测试完后,我又批量添加了几行数据,方便下面方法的测试。

// 以下就是我添加的数据
list.add(new User("liSi","女",20));
list.add(new User("wangWu","男",22));
list.add(new User("zhaoLiu","男",20));
list.add(new User("xiaoQi","女",21));

简单查询/单条件

        可以组合多种类型的搜索查询。我们将从简单的文本匹配查询开始。单条件准确查询主要用到的关键字是term。而模糊查询就需要用到match。而match这里就不演示了。

/*** 单条件查询*/
@GetMapping("/search")
public void search() throws IOException {SearchResponse<User> response = elasticConfig.esClient().search(s -> s.index("user").query(q -> q.term(e -> e.field("age").value("20"))), User.class);// 获取查询后的命中条数:其中包括 TotalHitsRelation 以及 totalTotalHits total = response.hits().total();boolean isExactResult = total.relation() == TotalHitsRelation.Eq;if (isExactResult) {log.info("There are " + total.value() + " results");} else {log.info("There are more than " + total.value() + " results");}// 解析查询到的所有信息List<Hit<User>> hits = response.hits().hits();for(Hit<User> hit : hits) {log.info("id,{}", hit.id());}
}

多条件查询 / 范围查询

        Elasticsearch允许将单个查询组合起来,以构建更复杂的搜索请求。当前数据有五条,为了更好的多条件查询,我又增加了5条数据。多条件查询用到的关键字主要就是bool

// 起初的5条数据
list.add(new User("zhangSan","男",18));
list.add(new User("liSi","女",20));
list.add(new User("wangWu","男",22));
list.add(new User("zhaoLiu","男",20));
list.add(new User("xiaoQi","女",21));
// 以下就是我添加的数据
list.add(new User("zhangSan","男",20));
list.add(new User("zhangSan","男",21));
list.add(new User("zhangSan","男",22));
list.add(new User("zhangSan","男",23));
list.add(new User("zhangSan","男",24));
/*** 多条件查询*/
@GetMapping("/batchSearch")
public void batchSearch() throws IOException {// 查询性别Query sex = MatchQuery.of(m -> m.field("sex").query("男"))._toQuery();// 查询年龄区间Query age = RangeQuery.of(r -> r.field("age").lte(JsonData.of(20)).gte(JsonData.of(18)))._toQuery();// 结合性别和年龄区间查询来搜索用户索引SearchResponse<User> response = elasticConfig.esClient().search(s -> s.index("user").query(q -> q.bool(b -> b.must(sex).must(age))),User.class);// 获取查询后的命中条数:其中包括 TotalHitsRelation 以及 totalTotalHits total = response.hits().total();boolean isExactResult = total.relation() == TotalHitsRelation.Eq;if (isExactResult) {log.info("There are " + total.value() + " results");} else {log.info("There are more than " + total.value() + " results");}// 解析查询到的所有信息List<Hit<User>> hits = response.hits().hits();for(Hit<User> hit : hits) {log.info("id,{}", hit.id());}
}

分页查询

        主要就是Elasticsearch语法中的from与size表示:当前页的开始索引处以及每页条数。

/*** 分页查询*/
@GetMapping("/searchByPage")
public void searchByPage() throws IOException {// 假设每页3条数据 那么查询第二页的参数就是:开始索引处为(2 - 1) * 3 = 3 以及 每页条数3SearchResponse<User> response = elasticConfig.esClient().search(b -> b.index("user").from(3).size(3),User.class);log.info("查询到的总条数为,{}",response.hits().total().value());List<Hit<User>> hits = response.hits().hits();for(Hit<User> hit : hits) {log.info("查询到的id,{}", hit.id());}
}

查询所有索引数据

/*** get all index data*/
@GetMapping("/getAllIndex")
public void getAllIndex() throws IOException {SearchResponse<User> response = elasticConfig.esClient().search(s -> s.index("user"),User.class);// 解析查询到的所有信息List<Hit<User>> hits = response.hits().hits();for(Hit<User> hit : hits) {log.info(String.valueOf(hit.source()));}
}


http://www.ppmy.cn/news/419990.html

相关文章

浏览器之BFC

浏览器之BFC 什么是BFCBFC的特性特性1&#xff1a;BFC会阻止垂直外边距折叠①相邻兄弟元素margin重叠问题②父子元素margin重叠问题 特性2&#xff1a;BFC不会重叠浮动元素BFC可以包含浮动----清除浮动 什么是BFC Block formatting context直译为"块级格式化上下文Block …

最便宜android手机型号,价格低但性价比非常高,这三款机型你可吗?

价格低但性价比非常高&#xff0c;这三款机型你可吗&#xff1f; 2020-08-24 13:41:31 0点赞 0收藏 0评论 时间到了8月&#xff0c;许多5G手机在不同程度上降低了价格。目前&#xff0c;千元机市场上有很多性价比很高的5G手机&#xff0c;今天我们来介绍三款都不超过1600元的机…

iPhonexr安兔兔html5测试,放心剁手!iPhone XR安兔兔跑分提前泄露,性能几无缩水...

今天15点整&#xff0c;最受关注的苹果手机iPhone XR即将开启预售&#xff0c;想必大家也都摩拳擦掌&#xff0c;跃跃欲试。此前我们知道&#xff0c;iPhone XR的处理器和iPhone XS系列一样&#xff0c;均为苹果A12 Bionic&#xff0c;理论上说性能十分强劲。不过有阴谋论者猜测…

android 国内各厂商,安卓手机性价比榜单更新,各家厂商占据不同价位段市场

Android手机的性价比榜单在近期迎来更新&#xff0c;统计周期范围是4月1日-4月30日的国内手机市场&#xff0c;羽度非凡第一眼看到各个价位段的4月份性价比榜单时&#xff0c;第一感觉还是非常欣慰的&#xff0c;因为相较以往的性价比榜单&#xff0c;最新的性价比榜单中&#…

从Realme GT的安兔兔跑分开始谈起

你还敢相信安兔兔吗&#xff1f;本人于2021年6月18日买入Realme GT这款手机&#xff0c;虽然Realme还是上市不久的手机品牌&#xff0c;但我还是被当时其超高的性价比所吸引&#xff0c;骁龙888的旗舰级满血配置&#xff0c;安兔兔跑分826388&#xff0c;位于当月第四&#xff…

TS系列之工具类型Partial、Required、Pick、Record详解,示例

TS系列之工具类型Partial、Required、Pick、Record详解&#xff0c;示例 文章目录 前言一、Partial<Type>二、Required<Type>三、Pick<Type, Keys>四、Record<Keys, Type>总结 前言 本片文章主要利用上一篇所学的keyof做一个延申与扩展的学习。在Type…

android手机性价比,最新Android手机性价比榜:2000元以内谁最强?

5月10日&#xff0c;安兔兔公布了4月份Android手机性价比榜&#xff0c;3、4月份是新机高发期&#xff0c;所以这次更新了不少新机。 此次榜单同样划分五个段位&#xff0c;分别是0-1999元价位段、2000-2999元价位段、3000-3999元价位段、4000-4999元价位段、5000元以上价位段。…

大数据之路书摘:走近大数据——从阿里巴巴学习大数据系统体系架构

文章目录 1.数据采集层2.数据计算层3.数据服务层4.数据应用层 在大数据时代&#xff0c;人们比以往任何时候更能收集到更丰富的数据。但是如果不能对这些数据进行有序、有结构地分类组织和存储&#xff0c;如果不能有效利用并发掘它&#xff0c;继而产生价值&#xff0c;那么它…