ElasticSearch版本:7.6.2
Springboot版本:2.3.12.RELEASE
springboot、es版本对应关系
Elasticsearch Clients列表
Java High Level REST Client参考文档
引入依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!-- Spring Data Release Train Spring Data Elasticsearch Elasticsearch Spring Framework Spring Boot-->
<!-- Neumann[1] 4.0.x[1] 7.6.2 5.2.12 2.3.x-->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
</dependency>
实例化RestHighLevelClient
@Configuration
public class ElasticSearchConfig {
@Bean
public RestHighLevelClient restHighLevelClient() {
return new RestHighLevelClient(
RestClient.builder(
new HttpHost("127.0.0.1", 9200, "http")));
}
}
查询
SearchRequest多条件查询
分组查询并对结果排序
@Test
public void testSearchGroupby() throws Exception{
SearchRequest searchRequest = new SearchRequest("trafficlight_error_log");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.rangeQuery("errorTime").gte("1673403774000").lte("1673414574000"));
searchSourceBuilder.query(boolQueryBuilder);
// 分组排序,size:分组之后前N条数据,sort:.key:按key排序;.count:按count结果排序
TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("aIntersectionId_count").field(
"aIntersectionId").size(1000).order(BucketOrder.key(true));
TermsAggregationBuilder termsAggregationBuilder2 = AggregationBuilders.terms("errorMsg_count").field(
"errorMsg.keyword").order(BucketOrder.count(true));
// 多条件分组查询
termsAggregationBuilder.subAggregation(termsAggregationBuilder2);
searchSourceBuilder.aggregation(termsAggregationBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
// System.out.println(searchResponse.getAggregations().asMap().get("aIntersectionId_count").getClass().getSimpleName());
ParsedLongTerms aIntersectionId_count = (ParsedLongTerms) searchResponse.getAggregations().asMap().get("aIntersectionId_count");
Iterator<? extends Terms.Bucket> iterator = aIntersectionId_count.getBuckets().iterator();
// 遍历
while (iterator.hasNext()) {
Terms.Bucket next = iterator.next();
System.out.println(next.getKey());
System.out.println(next.getDocCount());
// System.out.println(next.getAggregations().asMap().get("errorMsg_count").getClass().getSimpleName());
ParsedStringTerms terms = (ParsedStringTerms) next.getAggregations().asMap().get("errorMsg_count");
Iterator<? extends Terms.Bucket> iterator1 = terms.getBuckets().iterator();
while (iterator1.hasNext()) {
Terms.Bucket next1 = iterator1.next();
System.out.println(next1.getKey());
System.out.println(next1.getDocCount());
}
System.out.println("+++++++++++++++++++++");
}
}
GetRequest根据文档ID查询
public ArticleVO getDocument(String articleId) {
try {
GetRequest getRequest = new GetRequest(indexName, articleId);
GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
return JSON.parseObject(getResponse.getSourceAsString(), ArticleVO.class);
} catch (IOException ex) {
log.error(ex.getMessage());
}
return null;
}
termsQuery多值匹配
termsQuery 是 Elasticsearch 中的一种查询类型,用于查找文档中某个字段值在给定的一组多个值中的文档。它与 termQuery 类似,但 termsQuery 可以同时匹配多个值,而不是单一的值。
当需要匹配字段中存在多个可能值时,termsQuery 是一个合适的选择。
例如,我希望通过多个标签搜索到至少有一个标签相同的文章。
// 存在ES的 待查询的文章集合:
// "dataSetLabelList" : ["1231","777","888"],
// 查询条件:
// {
// "terms": {
// "dataSetLabelList": ["1231","12312","3112"]
// }
// }
// bool 查询
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
// 至少有一个标签相同,使用termsQuery,dataSetLabelList必须是keyword且是列表类型,带查询的内容也应该是列表类型
boolQueryBuilder.must(QueryBuilders.termsQuery("dataSetLabelList", Arrays.asList(dto.getDataSetLabel().split(","))));
排序
自定义脚本排序
自定义脚本排序是为了满足复杂的排序需求,通常用于标准的排序功能无法满足业务需求的场景。通过脚本排序,您可以根据文档的字段值或其他动态计算值来决定排序规则。
常见场景:
- 电商场景中,可以用商品销量、评分和库存进行加权排序。
- 博客场景中,可以根据博文的创建时间、阅读量进行加权排序
以博客场景为例,我需要优先将近三十天创建的博客排在前面,再按发布时间、浏览量进行降序排列
// 构建搜索条件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 分页查询
int begin = (query.getPageNum() - 1) * query.getPageSize();
searchSourceBuilder.from(begin);
searchSourceBuilder.size(query.getPageSize());
// bool 查询
searchSourceBuilder.query(boolQuery(query));
// 脚本排序,动态计算排序优先级,优先将7天内的文档排在前面
// 如果文档的 createTime 距离当前时间小于等于7天,返回 优先值 0。
// 如果文档的 createTime 超过7天,返回 次优先值 1。
Script script = new Script(
Script.DEFAULT_SCRIPT_TYPE,
Script.DEFAULT_SCRIPT_LANG,
"doc['createTime'].value >= params.threshold ? 0 : 1",
org.elasticsearch.common.collect.Map.of("threshold", System.currentTimeMillis() - 7 * 24 * 60 * 60 * 1000L) // 参数传递
);
// 先按优先级排序
searchSourceBuilder.sort(
SortBuilders.scriptSort(script,ScriptSortBuilder.ScriptSortType.NUMBER).order(SortOrder.ASC)
);
// 次级排序 再按实际内容排序
searchSourceBuilder.sort("browseNum", SortOrder.DESC);
searchSourceBuilder.sort("publishTime", SortOrder.DESC);