springboot+elasticsearch,Springboot整合es

  springboot+elasticsearch,Springboot整合es

  

目录

概述添加专家依赖配置应用程序。阳明海运股份有限公司创建索引对象跳羚操作萨尔瓦多数据的三种方式实现索引对应的贮藏室仓库文档操作文档保存、查询、删除分页查询与滚动查询萨尔瓦多深度分页相对滚动查询跳羚集成萨尔瓦多基本使用在试验中测试

 

  

概述

本文介绍Spring Boot项目中整合弹性搜索并实现创建、读取、更新和删除操作,包括分页、滚动等功能。

 

  

添加Maven依赖

相关性groupIdorg.springframework.boot/groupId artifact id spring-boot-starter-data-elastic search/artifact id/dependency

 

  

配置application.yml

春天:弹性研究:休息:尿:尿192 .19363636465

 

  

创建索引对象

包com。练习。麋鹿研究。实体;导入cn。胡工具。核心。约会。日期时间;进口龙目岛。数据;导入org。spring框架。数据。注释。id;导入org。spring框架。数据。弹性搜索。注释。文档;导入Java。util。日期;/* * * * @描述:文档模型* @版本:v 1。0 .0 * @ Date 3360 2021/12/22 14:08 */@ Document(index name= article )@ data公共类文章实体{ @ Id私有字符串id;私有字符串标题;私有字符串内容;私有整数使用者辩证码私人日期创建时间=日期时间。now();}

 

  

SpringBoot操作ES数据的三种方式

实现弹性研究接口引入ElasticsearchRestTemplate引入弹性搜索操作

 

  

实现索引对应的Repository

包com。练习。麋鹿研究。知识库;导入com。练习。麋鹿研究。实体。文章实体;导入org。spring框架。数据。弹性搜索。知识库。弹性研究;/* * * * @描述:文章数据操作接口* @版本:v 1。0 .0 * @ Date 3360 2021/12/22 14:18 */公共接口文章知识库扩展ElasticsearchRepositoryArticleEntity,String {}

 

  

文档操作

下面可以使用这个文章知识库来操作萨尔瓦多中的文章数据。

 

  我们这里没有手动创建这个文章对应的索引,由弹性搜索默认生成。

  下面的接口,实现了板簧罩中对萨尔瓦多数据进行插入、更新、分页查询、滚动查询、删除等操作。可以作为一个参考。

  其中,使用了贮藏室仓库来获取、保存、删除萨尔瓦多数据;使用ElasticsearchRestTemplate或弹性搜索操作来进行分页/滚动查询。

  

文档保存、查询、删除

包com。练习。麋鹿研究。控制器。c

 

  ontroller;import com.practice.elkstudy.entity.ArticleEntity;import com.practice.elkstudy.repository.ArticleRepository;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;import java.util.Optional;/** * @Description : article控制类 * @Version : V1.0.0 * @Date : 2021/12/22 14:11 */@RestController@RequestMapping("/elk")public class ArticleController { @Resource private ArticleRepository articleRepository; /** * 根据文档id查询数据 * * @param id 文档id * @return 文档详情 */ @GetMapping("/byId") public String findById(@RequestParam String id) { Optional<ArticleEntity> record = articleRepository.findById(id); return record.toString(); } /** * 保存文档信息 * * @param article 文档详情 * @return 保存的文档信息 */ @PostMapping("/saveArticle") public String saveArticle(@RequestBody ArticleEntity article) { ArticleEntity result = articleRepository.save(article); return result.toString(); }@DeleteMapping("/deleteById") public String deleteArticle(@RequestParam String id) { articleRepository.deleteById(id); return "success"; }}

 

  

分页查询与滚动查询

package com.practice.elkstudy.controller.controller;import com.practice.elkstudy.entity.ArticleEntity;import org.elasticsearch.index.query.BoolQueryBuilder;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.domain.PageRequest;import org.springframework.data.elasticsearch.core.ElasticsearchOperations;import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;import org.springframework.data.elasticsearch.core.SearchHit;import org.springframework.data.elasticsearch.core.SearchHits;import org.springframework.data.elasticsearch.core.SearchHitsImpl;import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;import org.springframework.util.StringUtils;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import java.util.Collections;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Objects;import java.util.stream.Collectors;/** * @Description : article高级查询 * @Version : V1.0.0 * @Date : 2021/12/22 15:10 */@RestController@RequestMapping("/elk")public class ArticleAdvanceController { @Autowired private ElasticsearchRestTemplate restTemplate; @Autowired private ElasticsearchOperations operations; /** * 分页查询 * * @param pageNum 页码,从0开始 * @param pageSize 分页大小 * @return 查询结果 */ @GetMapping("/queryPage") public String queryPage(@RequestParam int pageNum, @RequestParam int pageSize) { NativeSearchQuery query = new NativeSearchQuery(new BoolQueryBuilder()); query.setPageable(PageRequest.of(pageNum, pageSize)); // 方法1 SearchHits<ArticleEntity> search = restTemplate.search(query, ArticleEntity.class); // 方法2 // SearchHits<ArticleEntity> search = operations.search(query, ArticleEntity.class); List<ArticleEntity> articles = search.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList()); return articles.toString(); } /** * 滚动查询 * * @param scrollId 滚动id * @param pageSize 分页大小 * @return 查询结果 */ @GetMapping(value = "/scrollQuery") public String scroll(String scrollId, Integer pageSize) { if (pageSize == null pageSize <= 0) { return "please input query page num"; } NativeSearchQuery query = new NativeSearchQuery(new BoolQueryBuilder()); query.setPageable(PageRequest.of(0, pageSize)); SearchHits<ArticleEntity> searchHits; if (StringUtils.isEmpty(scrollId) scrollId.equals("0")) { // 开启一个滚动查询,设置该scroll上下文存在60s // 同一个scroll上下文,只需要设置一次query(查询条件) searchHits = restTemplate.searchScrollStart(60000, query, ArticleEntity.class, IndexCoordinates.of("article")); if (searchHits instanceof SearchHitsImpl) { scrollId = ((SearchHitsImpl) searchHits).getScrollId(); } } else { // 继续滚动 searchHits = restTemplate.searchScrollContinue(scrollId, 60000, ArticleEntity.class, IndexCoordinates.of("article")); } List<ArticleEntity> articles = searchHits.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList()); if (articles.size() == 0) { // 结束滚动 restTemplate.searchScrollClear(Collections.singletonList(scrollId)); scrollId = null; } if (Objects.isNull(scrollId)) { Map<String, String> result = new HashMap<>(2); result.put("articles", articles.toString()); result.put("message", "已到末尾"); return result.toString(); } else { Map<String, String> result = new HashMap<>(); result.put("count", String.valueOf(searchHits.getTotalHits())); result.put("pageSize", String.valueOf(articles.size())); result.put("articles", articles.toString()); result.put("scrollId", scrollId); return result.toString(); } }}

 

  

ES深度分页 vs 滚动查询

之前遇到的一个问题,日志检索的接口太慢了。

 

  开始使用的是深度分页,即1,2,3…10,这样的分页查询,查询条件较多(十多个参数)、查询数据量较大(单个日志索引约2亿条数据)。

  分页查询速度慢的原因在于:ES的分页查询,如查询第100页数据,每页10条,是先从每个分区(shard,一个索引默认是5个shard)中把命中的前100*10条数据查出来,然后协调节点进行合并操作,最后给出100页的数据。也就是说,实际被加载到内存的数据远远超过理想情况。

  这样,索引分片数越多,查询页数越多,查询速度就越慢。ES默认的max_result_window是10000条,也就是正常情况下,用分页查询到10000条数据时,就不会在返回下一页数据了。

  如果不需要进行跳页,比如直接查询第100页数据,或者数据量非常大,那么可以考虑用scroll查询。在scroll查询下,第1次需要根据查询参数开启一个scroll上下文,设置上下文缓存时间。以后的滚动只需要根据第一次返回的scrollId来进行即可。

  scroll只支持往下滚动,如果想要往前滚动,还可以根据scrollId缓存查询结果,这样就可以实现上下文滚动查询了一一就像大家经常使用的淘宝商品检索时上下滚动一样。

  

 

  

SpringBoot集成ES基本使用

#配置es#Liunx 上的ip地址和配置端口号spring.elasticsearch.rest.uris=192.168.113.129:9200

 

  

在test中测试

import com.alibaba.fastjson.JSON;import com.hzx.pojo.User;import com.hzx.utils.ESconst;import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;import org.elasticsearch.action.bulk.BulkRequest;import org.elasticsearch.action.bulk.BulkResponse;import org.elasticsearch.action.delete.DeleteRequest;import org.elasticsearch.action.delete.DeleteResponse;import org.elasticsearch.action.get.GetRequest;import org.elasticsearch.action.get.GetResponse;import org.elasticsearch.action.index.IndexRequest;import org.elasticsearch.action.index.IndexResponse;import org.elasticsearch.action.search.SearchRequest;import org.elasticsearch.action.search.SearchResponse;import org.elasticsearch.action.support.master.AcknowledgedResponse;import org.elasticsearch.action.update.UpdateRequest;import org.elasticsearch.action.update.UpdateResponse;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 org.elasticsearch.common.unit.TimeValue;import org.elasticsearch.common.xcontent.XContentType;import org.elasticsearch.index.query.QueryBuilders;import org.elasticsearch.index.query.TermQueryBuilder;import org.elasticsearch.search.SearchHit;import org.elasticsearch.search.builder.SearchSourceBuilder;import org.elasticsearch.search.fetch.subphase.FetchSourceContext;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import java.io.IOException;import java.util.ArrayList;import java.util.concurrent.TimeUnit;@Autowiredprivate RestHighLevelClient client;@Testvoid contextLoads() throws IOException { //创建索引请求 CreateIndexRequest request = new CreateIndexRequest("hong_index"); //客户端执行请求 IndicesClient create创建请求 RequestOptions.DEFAULT默认请求参数 CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT); //获取返回的参数 System.out.println(createIndexResponse);}@Testvoid test2() throws IOException { //获取指定索引库 GetIndexRequest request = new GetIndexRequest("hong_index2"); //判断获取索引是否存在 boolean exists = client.indices().exists(request,RequestOptions.DEFAULT); //如果索引存在就返回为true 或者 为false System.out.println(exists);}@Testvoid test3() throws IOException { //删除指定索引库 DeleteIndexRequest request = new DeleteIndexRequest("hong_index"); //获取删除索引 AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT); //检查索引是否被删除 System.out.println(delete.isAcknowledged());} //测试添加文档 @Test void test4() throws IOException { //创建对象 User user = new User("枣信",18); //创建索引库 IndexRequest request = new IndexRequest("hong_index"); //规则 为 put /hong_index/_doc/1 //创建的id request.id("1"); //创建的时间 request.timeout(TimeValue.timeValueSeconds(1));// request.timeout("1s"); //将数据放入到请求 JSON.toJSONString(user)将对象转换为json request.source(JSON.toJSONString(user), XContentType.JSON); //客户端发送请求 向索引中添加数据 IndexResponse indices = client.index(request, RequestOptions.DEFAULT); //获取返回的json对象 System.out.println(indices.toString()); //获取发送请求的状态 添加为CREATED 更新为OK System.out.println(indices.status()); }//获取文档信息@Testvoid test6() throws IOException { //根据索引传入的id获取 GetRequest getRequest = new GetRequest("hong_index","1"); //通过get获取信息 GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT); //根据指定的Source获取对应内容 System.out.println(getResponse.getSourceAsString()); //打印json对象 System.out.println(getResponse);}//更新 修改信息@Testvoid test7() throws IOException { //根据索引库传入的id更新 UpdateRequest updateRequest = new UpdateRequest("hong_index","1"); //更新时间 updateRequest.timeout("1s"); //创建对象 User user = new User("李四", 26); //更新 将对象转换为json updateRequest.doc(JSON.toJSONString(user),XContentType.JSON); //客户端发送请求,进行更新 UpdateResponse update = client.update(updateRequest, RequestOptions.DEFAULT); //获取更新状态 System.out.println(update.status());}//删除文档信息@Testvoid test8() throws IOException { //根据传入的索引id进行删除 DeleteRequest request = new DeleteRequest("hong_index","1"); //发送请求,删除 DeleteResponse delete = client.delete(request, RequestOptions.DEFAULT); //获取删除的状态 没有删除成功为NOT_FOUND 删除成功为OK System.out.println(delete.status());}//批量添加数据@Testvoid test9() throws IOException { //创建批量添加 BulkRequest bulkRequest = new BulkRequest(); //添加时间 bulkRequest.timeout("8s"); //创建一个arraylist集合 ArrayList<User> userList = new ArrayList<>(); userList.add(new User("李四",19)); userList.add(new User("王五",25)); userList.add(new User("赵刚",30)); userList.add(new User("张三",21)); userList.add(new User("赵六",36)); userList.add(new User("小武",20)); //批量处理请求 for (int i = 0; i < userList.size(); i++) { //批量更新和删除 在这修改对应的请求即可 不添加id(""+(i+1)) 会默认随机id,在大数据情况下,让他默认随机id bulkRequest.add(new IndexRequest("hong_index").id(""+(i+1)).source(JSON.toJSONString(userList.get(i)),XContentType.JSON)); } //批量添加发送请求 BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT); //获取批量添加的状态 返回false代表添加成功 System.out.println(bulk.hasFailures());}//查询索引信息@Testvoid test10() throws IOException { //查询 SearchRequest searchRequest = new SearchRequest(ESconst.ES_INDEX); //构建搜索条件 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); //查询条件,可以使用QueryBuilders工具来实现 // QueryBuilders.termQuery精确查询 // QueryBuilders.matchQuery()查询所有 TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "李四"); //查询的时间 sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS)); //将查询的sourceBuilder放入searchRequest中 searchRequest.source(sourceBuilder); //发送请求 SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT); //获取信息 System.out.println(JSON.toJSONString(search.getHits())); //循环变量出信息 for(SearchHit documentFields : search.getHits().getHits()){ //获取所有信息 System.out.println(documentFields.getSourceAsMap()); }}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持盛行IT。

 

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: