Springboot集成Elasticsearch High Level REST Client实现增删改查实战
创始人
2024-11-16 06:35:32
0

在这里插入图片描述

获取源码🚩

需要完整代码资料,请一键三连后评论区留下邮箱,安排发送!!!🤖

什么是High Level REST Client?

Elasticsearch 的 High Level REST Client 是一个用于与 Elasticsearch 进行交互的 Java 客户端库,它提供了比低级别的 REST 客户端更高级别的抽象。High Level REST Client 使用了 OkHttp 库作为底层的 HTTP 客户端,并且提供了自动重试、连接管理和错误处理等功能。它允许开发人员以面向对象的方式构建请求和解析响应,从而简化了与 Elasticsearch 的 REST API 的交互过程。

✔️优点:

  • 易用性:High Level REST Client 提供了丰富的 API,使得常见的 Elasticsearch 操作变得简单直观。
  • 自动重试和错误处理:它能够处理网络故障和重试失败的请求,减少了开发人员需要处理的异常情况。
  • 封装了 JSON 处理:它自动处理了请求和响应的序列化和反序列化,使得开发人员无需直接处理 JSON 字符串。
  • 连接管理:它提供了连接池管理,可以复用连接,提高性能。

❌缺点:

  • 依赖较大:由于其提供了丰富的功能,因此其依赖库和整体大小相对较大。
  • 性能开销:高层面的抽象可能会引入额外的性能开销,尤其是在高并发场景下。

High Level REST Client的核心

索引管理

CreateIndexRequest 和 CreateIndexResponse:用于创建一个新的索引。
GetIndexRequest 和 GetIndexResponse:用于获取索引的元数据。
DeleteIndexRequest 和 DeleteIndexResponse:用于删除一个索引。

文档操作

IndexRequest 和 IndexResponse:用于索引(或更新)一个文档。
UpdateRequest 和 UpdateResponse:用于更新已存在的文档。
GetRequest 和 GetResponse:用于检索一个文档。
DeleteRequest 和 DeleteResponse:用于删除一个文档。

搜索和聚合

SearchRequest 和 SearchResponse:用于执行搜索查询和聚合。
CountRequest 和 CountResponse:用于计算满足给定条件的文档数量。
ScrollRequest 和 ScrollResponse:用于滚动搜索结果,获取大量数据。

批量操作

BulkRequest 和 BulkResponse:用于执行批量操作,如批量索引、更新或删除多个文档。

request.source()等于DSL中query{}

Sprinboot集成High Level REST Client

创建索引

可以使用postman或者谷歌浏览器插件Elasticvue 创建:
在这里插入图片描述

{   "article_doc": {     "aliases": {},     "mappings": {       "properties": {         "author": {           "type": "keyword"         },         "category": {           "type": "keyword"         },         "content": {           "type": "text",           "analyzer": "ik_max_word",           "search_analyzer": "ik_smart"         },         "createTime": {           "type": "date",           "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"         },         "id": {           "type": "keyword"         },         "readCount": {           "type": "integer"         },         "title": {           "type": "text",           "analyzer": "ik_max_word",           "search_analyzer": "ik_smart"         }       }     },     "settings": {       "index": {         "routing": {           "allocation": {             "include": {               "_tier_preference": "data_content"             }           }         },         "number_of_shards": "1",         "provided_name": "article_doc",         "creation_date": "1721725035763",         "number_of_replicas": "1",         "uuid": "r55CXBCLSxO8aFWPtL1Niw",         "version": {           "created": "7130299"         }       }     }   } } 

添加pom依赖

 	org.elasticsearch 	elasticsearch 	7.14.0    	 org.elasticsearch.client 	elasticsearch-rest-high-level-client 	7.14.0  

编写配置类

@Configuration public class ElasticsearchConfig {     @Value("${elasticsearch.host}")     private String host;      @Value("${elasticsearch.port}")     private int port;      /*@Value("${elasticsearch.username}")     private String userName;      @Value("${elasticsearch.password}")     private String password;*/      /**      * 如果@Bean没有指定bean的名称,那么这个bean的名称就是方法名      */     @Bean     public RestHighLevelClient restHighLevelClient() {         return new RestHighLevelClient(                 RestClient.builder(                         new HttpHost(host, port, "http")                 )         );     }   } 

编写模型

@Data @TableName("tb_article") public class Article {     private String id;     private String author;     private String category;     private String title;     private String content;     private Integer readCount;     @JSONField(format = "yyyy-MM-dd HH:mm:ss")     private Date createTime; }  

编写接口服务类

获取索引结构接口

http://localhost:9000/articleDoc/getMapping
在这里插入图片描述

数据同步接口

/**      *  批量从数据库导入      * @throws IOException      */     public void importFromDb() throws IOException {         List
articleList = articleService.list(); BulkRequest bulkRequest = new BulkRequest(); for (Article doc : articleList) { String data = JSON.toJSONString(doc); IndexRequest indexRequest = new IndexRequest(Constant.ARTICLE_INDEX); indexRequest.id(doc.getId()).source(data, XContentType.JSON); bulkRequest.add(indexRequest); } BulkResponse response = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT); log.info("批量导入状态:{}, 耗时{}", response.status(), response.getTook().getSeconds()); }

在这里插入图片描述

精确查询

public List
searchByAuthor(String author) { try { // 构建查询条件(注意:termQuery 支持多种格式查询,如 boolean、int、double、string 等,这里使用的是 string 的查询) SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(QueryBuilders.termQuery("author", author)); SearchRequest searchRequest = new SearchRequest(Constant.ARTICLE_INDEX); searchRequest.source(searchSourceBuilder); // 执行查询,然后处理响应结果 SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT); // 根据状态和数据条数验证是否返回了数据 List
articleList = new ArrayList<>(); if (RestStatus.OK.equals(searchResponse.status()) && searchResponse.getHits().getTotalHits().value > 0) { SearchHits hits = searchResponse.getHits(); for (SearchHit hit : hits) { Article doc = JSON.parseObject(hit.getSourceAsString(), Article.class); articleList.add(doc); } } return articleList; } catch (IOException e) { log.error("精确查询异常:", e); return null; } }

在这里插入图片描述

全文查询

  • 查全部,
    java MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
    太简单,不再演示。
/**      *  全文查询      */     public List
matchQuery(String keyword) { try { // 构建查询条件 SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(QueryBuilders.multiMatchQuery(keyword,"title","content")); // 创建查询请求对象,将查询对象配置到其中 SearchRequest searchRequest = new SearchRequest(Constant.ARTICLE_INDEX); searchRequest.source(searchSourceBuilder); // 执行查询,然后处理响应结果 SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT); return getArticleListFromSearchResponse(searchResponse); } catch (IOException e) { log.error("全文查询异常", e); return null; } }

在这里插入图片描述

分页查询(带排序)

/**      *  分页查询      * @param page      */     public void pageSortQuery(Page
page) { try { // 构建查询条件 MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery(); // 创建查询源构造器 SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(matchAllQueryBuilder); // 设置分页 searchSourceBuilder.from((int) ((page.getCurrent()-1)*page.getSize())); searchSourceBuilder.size((int) page.getSize()); // 按照阅读量排序 searchSourceBuilder.sort("readCount", SortOrder.DESC); // 创建查询请求对象,将查询对象配置到其中 SearchRequest searchRequest = new SearchRequest(Constant.ARTICLE_INDEX); searchRequest.source(searchSourceBuilder); // 执行查询,然后处理响应结果 SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT); // 根据状态和数据条数验证是否返回了数据 page.setTotal(getHitTotal(searchResponse)); page.setRecords(getArticleListFromSearchResponse(searchResponse)); } catch (IOException e) { log.error("分页查询失败", e); } }

在这里插入图片描述

高亮查询✨

public List
highlightQuery(String keyword) { try { MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", keyword); HighlightBuilder highlightBuilder = new HighlightBuilder().field("title").preTags("").postTags(""); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(matchQueryBuilder); searchSourceBuilder.highlighter(highlightBuilder); searchSourceBuilder.size(100); SearchRequest searchRequest = new SearchRequest(Constant.ARTICLE_INDEX); searchRequest.source(searchSourceBuilder); SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT); List
articleList = new ArrayList<>(); if (RestStatus.OK.equals(searchResponse.status()) && searchResponse.getHits().getTotalHits().value > 0) { SearchHits hits = searchResponse.getHits(); for (SearchHit hit : hits) { Article doc = JSON.parseObject(hit.getSourceAsString(), Article.class); // 获取高亮的数据 HighlightField highlightField = hit.getHighlightFields().get("title"); System.out.println("高亮名称:" + highlightField.getFragments()[0].string()); // 替换掉原来的数据 Text[] fragments = highlightField.getFragments(); if (fragments != null && fragments.length > 0) { StringBuilder title = new StringBuilder(); for (Text fragment : fragments) { title.append(fragment); } doc.setTitle(title.toString()); } articleList.add(doc); } } return articleList; } catch (Exception e) { log.error("高亮查询失败", e); return null; } }

在这里插入图片描述

范围查询

/**      *  范围查询      *  时间文档表达式:https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html#date-math      * @return      */     public List
rangeQuery() { try { SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); //searchSourceBuilder.query(QueryBuilders.rangeQuery("price").gte(10000)); searchSourceBuilder.query(QueryBuilders.rangeQuery("createTime") .gte("now-2d").includeLower(true).includeUpper(true)); SearchRequest searchRequest = new SearchRequest(Constant.ARTICLE_INDEX); searchRequest.source(searchSourceBuilder); SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT); return getArticleListFromSearchResponse(searchResponse); } catch (Exception e) { log.error("范围查询失败", e); return null; } }

在这里插入图片描述

布尔查询(BooleanQuery)

bool 查询可以用来合并多个条件查询结果的布尔逻辑,它包含一下操作符:

must:多个查询条件必须完全匹配,相当于关系型数据库中的 and。
should:至少有一个查询条件匹配,相当于关系型数据库中的 or。
must_not: 多个查询条件的相反匹配,相当于关系型数据库中的 not。
filter:过滤满足条件的数据。
range:条件筛选范围。
gt:大于,相当于关系型数据库中的 >。
gte:大于等于,相当于关系型数据库中的 >=。
lt:小于,相当于关系型数据库中的 <。
lte:小于等于,相当于关系型数据库中的 <=。

public List
highlightQuery(String keyword) { try { MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", keyword); HighlightBuilder highlightBuilder = new HighlightBuilder().field("title").preTags("").postTags(""); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(matchQueryBuilder); searchSourceBuilder.highlighter(highlightBuilder); searchSourceBuilder.size(100); SearchRequest searchRequest = new SearchRequest(Constant.ARTICLE_INDEX); searchRequest.source(searchSourceBuilder); SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT); List
articleList = new ArrayList<>(); if (RestStatus.OK.equals(searchResponse.status()) && searchResponse.getHits().getTotalHits().value > 0) { SearchHits hits = searchResponse.getHits(); for (SearchHit hit : hits) { Article doc = JSON.parseObject(hit.getSourceAsString(), Article.class); // 获取高亮的数据 HighlightField highlightField = hit.getHighlightFields().get("title"); System.out.println("高亮名称:" + highlightField.getFragments()[0].string()); // 替换掉原来的数据 Text[] fragments = highlightField.getFragments(); if (fragments != null && fragments.length > 0) { StringBuilder title = new StringBuilder(); for (Text fragment : fragments) { title.append(fragment); } doc.setTitle(title.toString()); } articleList.add(doc); } } return articleList; } catch (Exception e) { log.error("高亮查询失败", e); return null; } }

在这里插入图片描述

聚合查询

在使用Elasticsearch时,更多会用到聚合操作,它类似SQL中的groupby操作。ES的聚合查询是先查出结果,然后对结果使用聚合函数做处理,常用的操作有:avg:求平均、max:最大值、min:最小值、sum:求和等。

在ES中聚合分为指标聚合和分桶聚合:

Metric 指标聚合:指标聚合对一个数据集求最大、最小、和、平均值等
Bucket 分桶聚合:除了有上面的聚合函数外,还可以对查询出的数据进行分组group by,再在组上进行游标聚合。

  • Metric 指标聚合
/**      *  指标查询      */     public int metricQuery() {         try {             MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();             searchSourceBuilder.query(matchAllQueryBuilder);             AggregationBuilder mostPopular = AggregationBuilders.max("mostPopular").field("readCount");             searchSourceBuilder.aggregation(mostPopular);             SearchRequest searchRequest = new SearchRequest(Constant.ARTICLE_INDEX);             searchRequest.source(searchSourceBuilder);             SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT); //            log.info("查询结果:{}", JSON.toJSONString(searchResponse));             Aggregations aggregations = searchResponse.getAggregations();             ParsedMax max = aggregations.get("mostPopular");             return (int) max.getValue();         } catch (Exception e) {             log.error("指标查询失败", e);             return -1;         }     } 

在这里插入图片描述

  • Bucket 分桶聚合

根据文章分类,统计文章数量。

/**      *  分桶聚合      * @return      */     public Map bucketQuery() {         try {             // 构建查询条件             MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();             // 创建查询源构造器             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();             searchSourceBuilder.query(matchAllQueryBuilder);              // 根据商品分类进行分组查询             TermsAggregationBuilder categoryGroup = AggregationBuilders.terms("categoryGroup").field("category");             searchSourceBuilder.aggregation(categoryGroup);              // 创建查询请求对象,将查询对象配置到其中             SearchRequest searchRequest = new SearchRequest(Constant.ARTICLE_INDEX);             searchRequest.source(searchSourceBuilder);             // 执行查询,然后处理响应结果             SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);             Aggregations aggregations = searchResponse.getAggregations();             ParsedStringTerms agg = aggregations.get("categoryGroup");             Map resultMap = new HashMap<>();             for (Terms.Bucket bucket : agg.getBuckets()) {                 resultMap.put(bucket.getKeyAsString(), bucket.getDocCount());             }             return resultMap;         } catch (Exception e) {             log.error("分桶聚合查询失败", e);             return null;         }     } 

在这里插入图片描述

为什么8.0版本要弃用?

在 Elasticsearch 8.0 版本中,High Level REST Client 被标记为弃用,主要是因为以下几个原因:

  • 维护成本:High Level REST Client 的维护成本较高,因为它需要随着 Elasticsearch 的发展而持续更新,以保持与 REST API 的兼容性。
  • 性能考量:为了提高性能和减少内存消耗,Elasticsearch 开发团队决定移除一些高成本的组件,High Level REST Client 因其封装层次较多而成为目标之一。
  • 替代方案:Elasticsearch 推出了新的 Java API Client,这是一个更轻量级、更高效的选择,它直接使用了 Elasticsearch 的内部协议,从而提供了更好的性能和更低的延迟。
    新的 Java API Client 能够更好地利用 Elasticsearch 的内部机制,减少序列化和反序列化的开销,同时也提供了更细粒度的控制和更高的灵活性。因此,Elasticsearch 推荐用户迁移到新的 Java API Client 上。

所以后续我会再整理个新的Java API Client 用法。与时俱进。

点赞收藏加评论

用到的时候再来看,收获更大。

相关内容

热门资讯

快手平台上的宝宝大眼睛特效是如... 快手宝宝大眼睛特效是一种美颜滤镜,它能够放大和美化用户的眼睛,创造出一种可爱、无辜的大眼效果。这种特...
为何QQ农场频繁遭遇服务器超时... qq农场服务器一直超时可能由于网络连接问题、服务器维护或更新、游戏本身bug,或者是用户设备性能不足...
请问,流行的端游吃鸡游戏的官方... "端游吃鸡服务器"通常指的是《绝地求生》(PlayerUnknown's Battlegrounds...
为什么互联网服务器不采用C语言... 互联网服务器不常用C语言编写,主要是因为现代开发更偏好使用如Python、Java等高级语言,它们提...
为何QQ群人数上限仅为600人... QQ好友数量上限为600人是因为腾讯公司为了优化用户体验,防止用户好友过多导致信息过载,同时也考虑到...
如何通过电脑键盘快捷键调整字体... 在大多数电脑上,你可以按住"Ctrl"键的同时按下"+"键(位于数字键盘上)来放大字体。如果你的电脑...
探索手机导航,如何轻松找到目的... 你可以使用手机上的地图应用程序,如Google Maps或Apple Maps,输入你想去的地方的名...
如何解决iPad提示的无法验证... 当iPad弹出“无法验证服务器身份”的提示时,意味着设备无法确认正在尝试连接的服务器的安全性。这可能...
解封微信账号究竟意味着什么? 解封微信账号指的是恢复被暂时封禁的微信账户的使用权限。这通常发生在用户违反了微信的服务条款或操作规则...
为何我的PUBG手游提示服务器... 手游PUBG显示服务器正在维修可能是因为官方正在进行更新或维护工作,以确保游戏的稳定性和安全性。玩家...