需要完整代码资料,请一键三连后评论区留下邮箱,安排发送!!!🤖
Elasticsearch 的 High Level REST Client 是一个用于与 Elasticsearch 进行交互的 Java 客户端库,它提供了比低级别的 REST 客户端更高级别的抽象。High Level REST Client 使用了 OkHttp 库作为底层的 HTTP 客户端,并且提供了自动重试、连接管理和错误处理等功能。它允许开发人员以面向对象的方式构建请求和解析响应,从而简化了与 Elasticsearch 的 REST API 的交互过程。
✔️优点:
❌缺点:
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{}
可以使用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" } } } } }
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; } }
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,再在组上进行游标聚合。
/** * 指标查询 */ 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; } }
根据文章分类,统计文章数量。
/** * 分桶聚合 * @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; } }
在 Elasticsearch 8.0 版本中,High Level REST Client 被标记为弃用,主要是因为以下几个原因:
所以后续我会再整理个新的Java API Client 用法。与时俱进。
用到的时候再来看,收获更大。