springboot 接入Elasticsearch的聚合查询

首先需要引入maven依赖

java 复制代码
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.12.1</version>
        </dependency>

增加es的配置文件,示例:

XML 复制代码
#es7.x
search:
  elastic:
    datalake:
      scheme: https
      host: asd-test.xxxx.net.cn
      port: 9200
      user: admin
      password: 123456
    index:
      fdt-rule: xxxxxxxxx

代码配置注册客户端

java 复制代码
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ElasticsearchConfig {

    @Value("${search.elastic.datalake.scheme}")
    private String esScheme;

    @Value("${search.elastic.datalake.host}")
    private String esHost;

    @Value("${search.elastic.datalake.port}")
    private int esPort;

    @Value("${search.elastic.datalake.user}")
    private String esUser;

    @Value("${search.elastic.datalake.password}")
    private String esPassword;

    private final Logger LOGGER = LoggerFactory.getLogger(getClass());

    @Bean
    public RestHighLevelClient client() {
        LOGGER.info("initialize elasticSearch7.x----eHost:{},esPort:{}", esHost, esPort);

        RestClientBuilder builder = RestClient.builder(
                new HttpHost(this.esHost, this.esPort, this.esScheme)
        );

        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        // 用户名、密码
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(this.esUser, this.esPassword));

        builder.setHttpClientConfigCallback(httpClientBuilder ->
                httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider)
        );

        return new RestHighLevelClient(builder);
    }


}
java 复制代码
/**
     * 执行es查询
     *
     * @param req          参数
     * @param groupByField 分组聚合字段
     * @param indexName    索引名称
     * @return SearchResponse
     */
    @SneakyThrows
    private SearchResponse getSearchResponse(DsrIncentiveSalaryCommonRequest req, String groupByField, String indexName) {
        // 创建搜索请求
        SearchRequest searchRequest = new SearchRequest(indexName);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // 创建布尔查询
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        // 来源不为空,则过滤工号
        if (DATA_TYPE_ONE.equals(req.getSourceEmp())) {
            boolQuery.must(getQueryBuilder(req.getEmpCode(), ADVISER_CODE));
        }
        if (DATA_TYPE_TWO.equals(req.getSourceEmp())) {
            boolQuery.must(getQueryBuilder(req.getEmpCode(), EMP_CODE));
        }
        // 其他筛选条件
        if (CollectionUtils.isNotEmpty(req.getCustNumList())) {
            List<String> custNumList = req.getCustNumList().stream().filter(StringUtils::isNotBlank).collect(Collectors.toList());
            boolQuery.must(QueryBuilders.termsQuery(CUST_NUM, custNumList));
        }
        if (CollectionUtils.isNotEmpty(req.getRequirementIdList())) {
            List<String> requirementIdList = req.getRequirementIdList().stream().filter(StringUtils::isNotBlank).collect(Collectors.toList());
            boolQuery.must(QueryBuilders.termsQuery(REQUIREMENT_ID, requirementIdList));
        }
        if (CollectionUtils.isNotEmpty(req.getRequirementStatusList())) {
            List<Integer> requirementStatusList = req.getRequirementStatusList().stream().filter(Objects::nonNull).collect(Collectors.toList());
            boolQuery.must(QueryBuilders.termsQuery("requirementStatus", requirementStatusList));
        }
        if (CollectionUtils.isNotEmpty(req.getSkuUniqList())) {
            List<String> skuUniqList = req.getSkuUniqList().stream().filter(StringUtils::isNotBlank).collect(Collectors.toList());
            boolQuery.must(QueryBuilders.termsQuery(UNIQUE_CODE, skuUniqList));
        }
        if (CollectionUtils.isNotEmpty(req.getTaskSubIdList())) {
            List<String> taskSubIdList = req.getTaskSubIdList().stream().filter(StringUtils::isNotBlank).collect(Collectors.toList());
            boolQuery.must(QueryBuilders.termsQuery(TASK_SUB_ID, taskSubIdList));
        }
        if (StringUtils.isNotBlank(req.getRequirementStartTime()) && StringUtils.isNotBlank(req.getRequirementEndTime())) {
            if (REAL_INDEX.equals(indexName)) {
                boolQuery.must(QueryBuilders.rangeQuery("requirementExecutedDate")
                        .lte(req.getRequirementEndTime())
                        .gte(req.getRequirementStartTime())
                );
            } else if (CollectionUtils.isEmpty(req.getRequirementIdList()) && CollectionUtils.isEmpty(req.getTaskSubIdList())) {
                boolQuery.must(QueryBuilders.rangeQuery("requirementStartTime")
                        .lte(req.getRequirementEndTime()));
                boolQuery.must(QueryBuilders.rangeQuery("requirementEndTime")
                        .gte(req.getRequirementStartTime()));
            }
        }
        searchSourceBuilder.query(boolQuery);

        // 构建聚合
        SumAggregationBuilder sumAggregation = AggregationBuilders.sum(TOTAL_VALUE).field("totalSalary");
        // 根据数据来源分别计算不同数据来源的激励积分,默认直接统计所有
        if (DATA_TYPE_ONE.equals(req.getSourceEmp())) {
            sumAggregation = AggregationBuilders.sum(TOTAL_VALUE)
                    .script(new Script("if (doc['adviserRatio'].size() > 0) { return doc['adviserRatio'].value * doc['totalSalary'].value; } else { return 0; }"));
        } else if (DATA_TYPE_TWO.equals(req.getSourceEmp())) {
            sumAggregation = AggregationBuilders.sum(TOTAL_VALUE)
                    .script(new Script("if (doc['dsrRatio'].size() > 0) { return doc['dsrRatio'].value * doc['totalSalary'].value; } else { return 0; }"));
        }

        TermsAggregationBuilder termsAgg = AggregationBuilders.terms(groupByField)
                .field(groupByField)
                .subAggregation(sumAggregation);
        searchSourceBuilder.aggregation(termsAgg).size(0);

        searchRequest.source(searchSourceBuilder);
        // 执行查询
        return client.search(searchRequest, RequestOptions.DEFAULT);
    }

    /**
     * 解析es查询结果
     *
     * @param searchResponse es查询结果
     * @param groupByField   分组字段
     * @return Map<String, BigDecimal>
     */
    private Map<String, BigDecimal> getEsResultMap(SearchResponse searchResponse, String groupByField) {
        Map<String, BigDecimal> salaryMap = new HashMap<>();
        // 通过分组字段获取聚合结果
        ParsedTerms parsedTerms = searchResponse.getAggregations().get(groupByField);
        for (Terms.Bucket bucket : parsedTerms.getBuckets()) {
            Aggregation totalValue = bucket.getAggregations().getAsMap().get(TOTAL_VALUE);
            if (totalValue instanceof ParsedSum) {
                ParsedSum parsedSum = (ParsedSum) totalValue;
                salaryMap.put(bucket.getKeyAsString(), BigDecimal.valueOf(parsedSum.getValue()));
            }
        }
        return salaryMap;
    }
相关推荐
带娃的IT创业者1 天前
WeClaw 日志分析实战:如何从海量日志中快速定位根因?
运维·python·websocket·jenkins·fastapi·架构设计·实时通信
贾斯汀玛尔斯1 天前
kinbana中无法在discover中显示在ES中创建的索引--解决方案
大数据·elasticsearch·搜索引擎
彭于晏Yan1 天前
MQTT消息服务
spring boot·后端·中间件
indexsunny1 天前
互联网大厂Java面试实战:从Spring Boot到微服务架构的深度解析
java·spring boot·spring cloud·kafka·prometheus·security·microservices
java1234_小锋1 天前
分享一套优质的SpringBoot+Vue咖啡商城系统
vue.js·spring boot·咖啡商城
悟空码字1 天前
滑块拼图验证:SpringBoot完整实现+轨迹验证+Redis分布式方案
java·spring boot·后端
小江的记录本1 天前
【MyBatis-Plus】Spring Boot + MyBatis-Plus 进行各种数据库操作(附完整 CRUD 项目代码示例)
java·前端·数据库·spring boot·后端·sql·mybatis
码界奇点1 天前
基于Spring Boot的医院药品管理系统设计与实现
java·spring boot·后端·车载系统·毕业设计·源代码管理
海南java第二人1 天前
Cursor 高级实战:从 Spring Boot 到微服务,AI 驱动的全流程开发指南
人工智能·spring boot·微服务
爱笑的源码基地1 天前
门诊his系统源码,中西医结合的数字化门诊解决方案
java·spring boot·源码·二次开发·门诊系统·云诊所系统·诊所软件源码