es总结记录

1、二次过滤“平均金额”

根据动态算出来的“平均金额”,通过外面来的“最大值”和“最小值”,去比对“平均金额”是否处在“最大值”和“最小值”之间,然后再根据“平均金额”排序

        //1-最低档,2-低档,3-高档,4-最高档
        List<Integer> priceGrade = Arrays.asList(1, 2, 3, 4);
//        List<Integer> priceGrade = Arrays.asList(1);

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        // 构建布尔查询
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

        //时间范围筛选
        boolQueryBuilder.must(QueryBuilders.rangeQuery("settlementTime")
                .gte(startDate.toInstant(ZoneOffset.of("+8")).toEpochMilli())
                .lte(endDate.toInstant(ZoneOffset.of("+8")).toEpochMilli() + 999));

        // 查询未删除订单
        boolQueryBuilder.must(QueryBuilders.matchQuery("deleted", false));

        // 行程单,主状态为“已结算”,子状态为“已转账”,2023-09-13确认
        boolQueryBuilder.must(QueryBuilders.matchQuery("status", ItineraryStatusEnum.HAD_SETTLED.getStatus()));
        boolQueryBuilder.must(QueryBuilders.matchQuery("childStatus", HadSettledChildStatusEnum.HAD_APPLY_TRANSFER.getStatus()));

        //查询非模板的数据
        QueryBuilder queryBuilder1 = QueryBuilders.boolQuery()
                .mustNot(QueryBuilders.existsQuery("isTemplate"));
        boolQueryBuilder.should(queryBuilder1);
        boolQueryBuilder.should(QueryBuilders.termQuery("isTemplate", false));
        //团单数
        AggregationBuilder countOidAgg = AggregationBuilders.count("count_oid").field("oid");
        //计算人数
        AggregationBuilder touristCountSumAgg = AggregationBuilders.sum("sum_touristCount").field("touristCount");
        //计算金额(相加)
        AggregationBuilder totalFeeSumAgg = AggregationBuilders.sum("sum_totalFee").field("totalFee");
        // 人均费用排序
        BucketSortPipelineAggregationBuilder bucketSortDesc = PipelineAggregatorBuilders.bucketSort(
                "sort_by_average_spending",
                Collections.singletonList(new FieldSortBuilder("average_spending").order(SortOrder.DESC))
        );
        // 映射map
        Map<String, String> params = new HashMap<>();
        params.put("totalFee", "sum_totalFee");
        params.put("touristCount", "sum_touristCount");
        // 锁定average_spending的值,使其大于1000,小于5000
        Map<String, String> bucketSelectorParams = new HashMap<>();
        bucketSelectorParams.put("average_spending", "average_spending");
        bucketSelectorParams.put("totalFee", "sum_totalFee");
        bucketSelectorParams.put("touristCount", "sum_touristCount");

        for (Integer integer : priceGrade) {
            // 动态参数
            Map<String, Object> scriptParams = new HashMap<>();
//            scriptParams.put("minSpending", 0);  // 动态赋值的最小值
//            scriptParams.put("maxSpending", 800000);  // 动态赋值的最大值
            //1-最低档,2-低档,3-高档,4-最高档
            switch (integer) {
                case 1:
                    if (contractPriceRange.getMinPrice() > 0) {
                        if (contractPriceRange.getMinPrice() > 1) {
                            scriptParams.put("minSpending", (contractPriceRange.getMinPrice() - 1) * 100);  // 动态赋值的最小值
                        } else {
                            scriptParams.put("minSpending", (contractPriceRange.getMinPrice()) * 100);  // 动态赋值的最小值
                        }
                    } else {
                        scriptParams.put("minSpending", 0);  // 动态赋值的最小值
                    }
                    scriptParams.put("maxSpending", contractPriceRange.getMedianPrice() * 100);  // 动态赋值的最大值
                    break;
                case 2:
                    scriptParams.put("minSpending", contractPriceRange.getMedianPrice() * 100);  // 动态赋值的最小值
                    scriptParams.put("maxSpending", contractPriceRange.getMinimumPrice() * 100);  // 动态赋值的最大值
                    break;
                case 3:
                    scriptParams.put("minSpending", contractPriceRange.getMinimumPrice() * 100);  // 动态赋值的最小值
                    scriptParams.put("maxSpending", contractPriceRange.getTopPrice() * 100);  // 动态赋值的最大值
                    break;
                case 4:
                    scriptParams.put("minSpending", contractPriceRange.getTopPrice() * 100);  // 动态赋值的最小值
                    scriptParams.put("maxSpending", (contractPriceRange.getMaxPrice() + 1) * 100);  // 动态赋值的最大值
                    break;
            }


            // 内存统计,根据酒店区分
            // bucket_selector 聚合,用于过滤平均花费在 minSpending 到 maxSpending 之间的桶
            BucketSelectorPipelineAggregationBuilder bucketSelector = PipelineAggregatorBuilders.bucketSelector(
                    "spending_filter",
                    bucketSelectorParams,
                    new Script(
                            ScriptType.INLINE,
                            "painless",
                            "params.totalFee > 0 && params.touristCount > 0 && (params.totalFee / params.touristCount) > params.minSpending && (params.totalFee / params.touristCount) <= params.maxSpending",
                            scriptParams
                    )
            );
            //聚合
            AggregationBuilder aggregationBuilder = AggregationBuilders
                    .terms("term_subTravelOid" + integer).field("subTravelOid")
                    .size(10000)
                    .subAggregation(AggregationBuilders.topHits("subTravelName").fetchSource(new String[]{"subTravelName"}, null).size(1))
                    .subAggregation(countOidAgg)
                    .subAggregation(touristCountSumAgg)
                    .subAggregation(totalFeeSumAgg)
                    .subAggregation(PipelineAggregatorBuilders.bucketScript(
                            "average_spending",
                            params,
                            new Script("params.totalFee / params.touristCount")))
                    .subAggregation(bucketSelector)
                    .subAggregation(bucketSortDesc);

            searchSourceBuilder.aggregation(aggregationBuilder);
        }

        searchSourceBuilder.query(boolQueryBuilder);

        SearchResponse searchResponse = esOperationUtil.getSearchResponse(searchSourceBuilder, ElasticIndexConstants.TRAVEL_ITINERARY_VISUALIZATION_INDEX);

2、使用es动态计算的值,不能使用AVG计算平均值

            Script script = new Script("doc['totalFee'].size() > 0 " +
                    "&& doc['touristCount'].size() > 0 " +
                    "&& doc['totalFee'].value > 0 " +
                    "&& doc['touristCount'].value > 0 ? doc['totalFee'].value / doc['touristCount'].value : 0");
            // 平均消费
            AvgAggregationBuilder averageFeePerTouristAgg = AggregationBuilders.avg("average_spending").script(script);

“minPrice”和“maxPrice”是使用es的AVG计算的平均价格(金额/人数)

而“perCapitaConsumption”这里的平均值,是使用的script手动先sum拿到全部的“金额”和sum拿到全部的“人数”去计算的

总结:动态计算的数值,不要单纯的使用AVG计算

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值