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;
    }
相关推荐
Flynt9 小时前
把公司项目迁到 Spring Boot 4.0:编译通过只是开始
java·spring boot·后端
yxlalm12 小时前
5.3解决超卖问题
java·spring boot·超卖
边境悍匪13 小时前
蜗牛学苑 Java 智能体学习 Day39|SpringAI 会话存储、Function‑Call 工具调用、MCP 思维导图复盘
java·开发语言·spring boot·学习·阿里云
xcl092515 小时前
全民健身智慧管理系统实战指南:从架构设计到部署落地
java·spring boot
Bs_MoneyMagnet15 小时前
基于springboot+vue的宠物殡葬管理平台的设计与实现 源码+文档
java·javascript·vue.js·spring boot·后端·宠物
ly768915 小时前
生产环境 Spring Boot 应用内存泄漏排查实战
java·spring boot·spring·内存泄漏·threadlocal·gc日志·堆转储
Elastic 中国社区官方博客15 小时前
Elasticsearch 向量数据库:几分钟内完成部署,以经济高效的方式扩展至数千亿规模
大数据·运维·数据库·elasticsearch·搜索引擎·ai·全文检索
行百里er17 小时前
Spring Insight 里上报 Span 为什么用 JDK HttpClient 而不是 RestTemplate
spring boot·spring cloud·监控
Bs_MoneyMagnet17 小时前
基于springboot+vue的家居生活商城平台的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring
微三云 - 廖会灵 (私域系统开发)17 小时前
Spring Boot实战:五级分销定价与自动分佣系统设计与实现
java·spring boot·后端