一,最终实现:查询条件及查询结果如下图所示
需要实现:分组,求和,聚合后排序,总计,分页
二, 需求分析:关于分组维度
es数据主键为:日期(年月日)+采购组织+采购组+门店
统计维度:可根据是否选择门店,按日或按月统计可分为四种情况
日+采购组织+采购组;采购组织+采购组;日+采购组织+采购组+门店;月+采购组织+采购组+门店;
按正常es多条件分组求和处理方式很麻烦,可参考网上写法。可以转变思路,把每个维度拼接成一个字段,即新增四个字段,多条件分组统计转化为单条件分组统计,实现起来会简单的多。如下图所示:
三,代码实现
关于聚合
难点在于聚合统计,及聚合统计后再合计
关于排序
聚合求和的字段排序与不需要聚合求和的字段区分开来,前者可以直接应用es特性直接排序,后者排序,对处理之后的数据lis排序,java特性排序对list排序
关于分页
es无法复杂聚合后排序,对处理之后的数据进行伪分页排序,并不是真正意义上的排序,可以减轻前端压力,对于后台是对所有的数据伪分页。
serviceImpl
public Page<ResFoodOrderInspectionVO> queryPageByOrgGroupLocationCodes(ReqFoodOrderInspectionVO reqVO) {
// 参数处理
paramDeal(reqVO);
Page<ResFoodOrderInspectionVO> page = new Page<>();
page.setPageSize(reqVO.getSize());
page.setPageNo(reqVO.getPage());
page.setOrderBy(reqVO.getOrderBy());
// 聚合查询
List<ResFoodOrderInspectionVO> resList = esService.queryGroupByOrgGroupLocationCode(reqVO);
if (CollectionUtils.isEmpty(resList)) {
return new Page<>();
}
// 百分率处理
percentDeal(resList);
// 非聚合字段排序处理
orderBy(resList, reqVO);
page.setTotalNum(resList.size());
page.setResult(pageHandle(resList, reqVO.getPage(), reqVO.getSize()));
return page;
}
@Override
public List<ResFoodOrderInspectionVO> queryGroupByOrgGroupLocationCode(ReqFoodOrderInspectionVO reqVO) {
log.info("食用订单巡检表查询条件:{}", reqVO.toString());
StopWatch stopwatch = new StopWatch();
stopwatch.start();
List<ResFoodOrderInspectionVO> resList = Lists.newArrayList();
SearchRequest searchRequest = new SearchRequest(EsOperateTables.FOOD_ORDER_INSPECTION.getAlias());
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.fetchSource(RES_FBASEFOODORDERINSPEC_FIELDS, null);
searchSourceBuilder.size(0);// 设置为0代表不需要取查询到的所有数据,只需要取聚合的相关的数据
BoolQueryBuilder booleanQuery = QueryBuilders.boolQuery();
// 组装查询条件
buildBooleanQuery(booleanQuery, reqVO);
searchSourceBuilder.query(QueryBuilders.constantScoreQuery(booleanQuery));
// 分组,统计,排序
FoodOrderInspectionConvertor.groupCountAgg(searchSourceBuilder, reqVO);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = null;
try {
searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
stopwatch.stop();
} catch (IOException e) {
log.error(ErrorMsgConstant.FOODORDERINSPECTION_QUERYES_ERROR, e);
throw new OrderCenterException(ErrorMsgConstant.FOODORDERINSPECTION_QUERYES_ERROR);
}
if (Objects.isNull(searchResponse)) {
return Collections.emptyList();
}
Terms terms = searchResponse.getAggregations().get(FoodOrderInspectionConstant.GROUPDIMENSION);
if (Objects.isNull(terms)) {
return Collections.emptyList();
}
// 包含门店,且按日统计时,需要判断总量,其他场景,总分组量实际不会大于10000,不需要判断
if (CollectionUtils.isNotEmpty(reqVO.getLocationCodes()) && !reqVO.getGroupMonth() && searchResponse.getHits().getTotalHits() > FoodOrderInspectionConstant.GROUP_RETURN_SIZE) {
throw new OrderCenterException(ErrorMsgConstant.GROUP_TOTALSIZE_TOOLONG);
}
// 组装数据
for (Terms.Bucket entry : terms.getBuckets()) {
resList.add(FoodOrderInspectionConvertor.toResVO(entry, reqVO));
}
// 取聚合统计后合计
Map<String, Aggregation> totalMap = searchResponse.getAggregations().getAsMap();
resList.forEach(v -> {
v.setResFoodOrderInspectionTotalVO(FoodOrderInspectionConvertor.buildTotal(totalMap));
});
log.info("食用订单巡检报表查询耗时:{}", stopwatch.getTotalTimeMillis());
return resList;
}
聚合求和及聚合合计字段处理
1.注意维度下数据量,如果大于10000条,多余的数据不会计入聚合统计,如下图说明
2.注意聚合求和和聚合合计的层级关系,聚合统计字段以子聚合关联,聚合合计字段与分组维度一个层级
/**
* 统计,排序
* 分组size含义:需要返回分组后的个数;如按某维度分组,10个结果,size=2,只会返回两个结果。应该小于10000
* 分组size测试:
* 条件:全部100家门店,日期5月份,包含门店,按日维度统计
* 结果:查询总量:19703 1,size>10000,程序异常;2,size=10000(查询时长大概30s),实际只取前10000条数据聚合返回,导致数据不准
* 处理:如果size>10000,抛业务异常,缩小范围
*
* @param searchSourceBuilder
* @param reqVO
*/
public static void groupCountAgg(SearchSourceBuilder searchSourceBuilder, ReqFoodOrderInspectionVO reqVO) {
//对聚合结果的排序 true为正序 false为倒序
Boolean sort = FoodOrderInspectionConstant.ASC.equals(reqVO.getSort()) ? true : false;
//聚合场景
TermsAggregationBuilder groupDimension = null;
if (CollectionUtils.isNotEmpty(reqVO.getLocationCodes()) && reqVO.getGroupMonth()) {
groupDimension = AggregationBuilders.terms(FoodOrderInspectionConstant.GROUPDIMENSION).field(convertToUnderScore(BaseFoodOrderInspectionVO::getMonthOrgGroupLocation)).size(FoodOrderInspectionConstant.GROUP_RETURN_SIZE);
} else if (CollectionUtils.isEmpty(reqVO.getLocationCodes()) && !reqVO.getGroupMonth()) {
groupDimension = AggregationBuilders.terms(FoodOrderInspectionConstant.GROUPDIMENSION).field(convertToUnderScore(BaseFoodOrderInspectionVO::getDayOrgGroup)).size(FoodOrderInspectionConstant.GROUP_RETURN_SIZE);
} else if (CollectionUtils.isEmpty(reqVO.getLocationCodes()) && reqVO.getGroupMonth()) {
groupDimension = AggregationBuilders.terms(FoodOrderInspectionConstant.GROUPDIMENSION).field(convertToUnderScore(BaseFoodOrderInspectionVO::getMonthOrgGroup)).size(FoodOrderInspectionConstant.GROUP_RETURN_SIZE);
} else if (CollectionUtils.isNotEmpty(reqVO.getLocationCodes()) && !reqVO.getGroupMonth()) {
groupDimension = AggregationBuilders.terms(FoodOrderInspectionConstant.GROUPDIMENSION).field(FoodOrderInspectionConstant._ID).size(FoodOrderInspectionConstant.GROUP_RETURN_SIZE);
} else {
return;
}
// 判断是否在聚合排序范围
List<String> fileds = Arrays.stream(ReqFoodOrderInspectionOderByVO.class.getDeclaredFields()).map(field -> field.getName()).collect(Collectors.toList());
if (fileds.contains(reqVO.getOrderBy())) {
groupDimension.order(BucketOrder.aggregation(reqVO.getOrderBy(), sort));
}
// 分组维度内取第一个元素
TopHitsAggregationBuilder topHits = null;
if (CollectionUtils.isNotEmpty(reqVO.getLocationCodes()) && !reqVO.getGroupMonth()) {
topHits = AggregationBuilders.topHits(FoodOrderInspectionConstant.TOP_HITS_ONE).size(1).fetchSource(RES_FBASEFOODORDERINSPEC_FIELDS, null);
} else {
topHits = AggregationBuilders.topHits(FoodOrderInspectionConstant.TOP_HITS_ONE).size(1).fetchSource(ORG_GROUP_LOCATION_FIELDS, null);
}
//聚合统计
SumAggregationBuilder replenishAdviceQtySum = AggregationBuilders.sum(FoodOrderInspectionConstant.REPLENISHADVICEQTY).field(convertToUnderScore(BaseFoodOrderInspectionVO::getReplenishAdviceQty));
SumAggregationBuilder actApproveProductNumSum = AggregationBuilders.sum(FoodOrderInspectionConstant.ACTAPPROVEPRODUCTNUM).field(convertToUnderScore(BaseFoodOrderInspectionVO::getActApproveProductNum));
SumAggregationBuilder actApproveQtySum = AggregationBuilders.sum(FoodOrderInspectionConstant.ACTAPPROVEQTY).field(convertToUnderScore(BaseFoodOrderInspectionVO::getActApproveQty));
SumAggregationBuilder actReplenishProductNumSum = AggregationBuilders.sum(FoodOrderInspectionConstant.ACTREPLENISHPRODUCTNUM).field(convertToUnderScore(BaseFoodOrderInspectionVO::getActReplenishProductNum));
SumAggregationBuilder actReplenishAdviceQtySum = AggregationBuilders.sum(FoodOrderInspectionConstant.ACTREPLENISHADVICEQTY).field(convertToUnderScore(BaseFoodOrderInspectionVO::getActReplenishAdviceQty));
SumAggregationBuilder addProductNumSum = AggregationBuilders.sum(FoodOrderInspectionConstant.ADDPRODUCTNUM).field(convertToUnderScore(BaseFoodOrderInspectionVO::getAddProductNum));
SumAggregationBuilder manualReplenishProductNumSum = AggregationBuilders.sum(FoodOrderInspectionConstant.MANUALREPLENISHPRODUCTNUM).field(convertToUnderScore(BaseFoodOrderInspectionVO::getManualReplenishProductNum));
SumAggregationBuilder aiReplenishProductNumSum = AggregationBuilders.sum(FoodOrderInspectionConstant.AIREPLENISHPRODUCTNUM).field(convertToUnderScore(BaseFoodOrderInspectionVO::getAiReplenishProductNum));
SumAggregationBuilder specialReplenishProductNumDqSum = AggregationBuilders.sum(FoodOrderInspectionConstant.SPECIALREPLENISHPRODUCTNUMDQ).field(convertToUnderScore(BaseFoodOrderInspectionVO::getSpecialReplenishProductNumDq));
SumAggregationBuilder specialReplenishProductNumTgSum = AggregationBuilders.sum(FoodOrderInspectionConstant.SPECIALREPLENISHPRODUCTNUMTG).field(convertToUnderScore(BaseFoodOrderInspectionVO::getSpecialReplenishProductNumTg));
SumAggregationBuilder specialReplenishProductNumYcSum = AggregationBuilders.sum(FoodOrderInspectionConstant.SPECIALREPLENISHPRODUCTNUMYC).field(convertToUnderScore(BaseFoodOrderInspectionVO::getSpecialReplenishProductNumYc));
SumAggregationBuilder orderProductNumSum = AggregationBuilders.sum(FoodOrderInspectionConstant.ORDERPRODUCTNUM).field(convertToUnderScore(BaseFoodOrderInspectionVO::getOrderProductNum));
SumAggregationBuilder orderQtySum = AggregationBuilders.sum(FoodOrderInspectionConstant.ORDERQTY).field(convertToUnderScore(BaseFoodOrderInspectionVO::getOrderQty));
SumAggregationBuilder adviceReplenishProductNumSum = AggregationBuilders.sum(FoodOrderInspectionConstant.ADVICEREPLENISHPRODUCTNUM).field(convertToUnderScore(BaseFoodOrderInspectionVO::getAdviceReplenishProductNum));
// 聚合统计后再合计
SumBucketPipelineAggregationBuilder replenishAdviceQtySumBucket = new SumBucketPipelineAggregationBuilder(FoodOrderInspectionConstant.REPLENISHADVICEQTYTOTAL, FoodOrderInspectionConstant.GROUPDIMENSION + FoodOrderInspectionConstant.GROUPFLAG + FoodOrderInspectionConstant.REPLENISHADVICEQTY);
SumBucketPipelineAggregationBuilder approveProductNumSumBucketAct = new SumBucketPipelineAggregationBuilder(FoodOrderInspectionConstant.ACTAPPROVEPRODUCTNUMTOTAL, FoodOrderInspectionConstant.GROUPDIMENSION + FoodOrderInspectionConstant.GROUPFLAG + FoodOrderInspectionConstant.ACTAPPROVEPRODUCTNUM);
SumBucketPipelineAggregationBuilder actApproveQtySumBucket = new SumBucketPipelineAggregationBuilder(FoodOrderInspectionConstant.ACTAPPROVEQTYTOTAL, FoodOrderInspectionConstant.GROUPDIMENSION + FoodOrderInspectionConstant.GROUPFLAG + FoodOrderInspectionConstant.ACTAPPROVEQTY);
SumBucketPipelineAggregationBuilder actReplenishProductNumSumBucket = new SumBucketPipelineAggregationBuilder(FoodOrderInspectionConstant.ACTREPLENISHPRODUCTNUMTOTAL, FoodOrderInspectionConstant.GROUPDIMENSION + FoodOrderInspectionConstant.GROUPFLAG + FoodOrderInspectionConstant.ACTREPLENISHPRODUCTNUM);
SumBucketPipelineAggregationBuilder actReplenishAdviceQtySumBucket = new SumBucketPipelineAggregationBuilder(FoodOrderInspectionConstant.ACTREPLENISHADVICEQTYTOTAL, FoodOrderInspectionConstant.GROUPDIMENSION + FoodOrderInspectionConstant.GROUPFLAG + FoodOrderInspectionConstant.ACTREPLENISHADVICEQTY);
SumBucketPipelineAggregationBuilder addProductNumSumBucket = new SumBucketPipelineAggregationBuilder(FoodOrderInspectionConstant.ADDPRODUCTNUMTOTAL, FoodOrderInspectionConstant.GROUPDIMENSION + FoodOrderInspectionConstant.GROUPFLAG + FoodOrderInspectionConstant.ADDPRODUCTNUM);
SumBucketPipelineAggregationBuilder manualReplenishProductNumSumBucket = new SumBucketPipelineAggregationBuilder(FoodOrderInspectionConstant.MANUALREPLENISHPRODUCTNUMTOTAL, FoodOrderInspectionConstant.GROUPDIMENSION + FoodOrderInspectionConstant.GROUPFLAG + FoodOrderInspectionConstant.MANUALREPLENISHPRODUCTNUM);
SumBucketPipelineAggregationBuilder aiReplenishProductNumSumBucket = new SumBucketPipelineAggregationBuilder(FoodOrderInspectionConstant.AIREPLENISHPRODUCTNUMTOTAL, FoodOrderInspectionConstant.GROUPDIMENSION + FoodOrderInspectionConstant.GROUPFLAG + FoodOrderInspectionConstant.AIREPLENISHPRODUCTNUM);
SumBucketPipelineAggregationBuilder specialReplenishProductNumDqSumBucket = new SumBucketPipelineAggregationBuilder(FoodOrderInspectionConstant.SPECIALREPLENISHPRODUCTNUMDQTOTAL, FoodOrderInspectionConstant.GROUPDIMENSION + FoodOrderInspectionConstant.GROUPFLAG + FoodOrderInspectionConstant.SPECIALREPLENISHPRODUCTNUMDQ);
SumBucketPipelineAggregationBuilder specialReplenishProductNumTgSumBucket = new SumBucketPipelineAggregationBuilder(FoodOrderInspectionConstant.SPECIALREPLENISHPRODUCTNUMTGTOTAL, FoodOrderInspectionConstant.GROUPDIMENSION + FoodOrderInspectionConstant.GROUPFLAG + FoodOrderInspectionConstant.SPECIALREPLENISHPRODUCTNUMTG);
SumBucketPipelineAggregationBuilder specialReplenishProductNumYcSumBucket = new SumBucketPipelineAggregationBuilder(FoodOrderInspectionConstant.SPECIALREPLENISHPRODUCTNUMYCTOTAL, FoodOrderInspectionConstant.GROUPDIMENSION + FoodOrderInspectionConstant.GROUPFLAG + FoodOrderInspectionConstant.SPECIALREPLENISHPRODUCTNUMYC);
SumBucketPipelineAggregationBuilder orderProductNumSumBucket = new SumBucketPipelineAggregationBuilder(FoodOrderInspectionConstant.ORDERPRODUCTNUMTOTAL, FoodOrderInspectionConstant.GROUPDIMENSION + FoodOrderInspectionConstant.GROUPFLAG + FoodOrderInspectionConstant.ORDERPRODUCTNUM);
SumBucketPipelineAggregationBuilder orderQtySumBucket = new SumBucketPipelineAggregationBuilder(FoodOrderInspectionConstant.ORDERQTYTOTAL, FoodOrderInspectionConstant.GROUPDIMENSION + FoodOrderInspectionConstant.GROUPFLAG + FoodOrderInspectionConstant.ORDERQTY);
SumBucketPipelineAggregationBuilder adviceReplenishProductNumSumBucket = new SumBucketPipelineAggregationBuilder(FoodOrderInspectionConstant.ADVICEREPLENISHPRODUCTNUMTOTAL, FoodOrderInspectionConstant.GROUPDIMENSION + FoodOrderInspectionConstant.GROUPFLAG + FoodOrderInspectionConstant.ADVICEREPLENISHPRODUCTNUM);
searchSourceBuilder.aggregation(groupDimension.subAggregation(topHits).subAggregation(replenishAdviceQtySum).subAggregation(actApproveProductNumSum)
.subAggregation(actApproveQtySum).subAggregation(actReplenishProductNumSum).subAggregation(actReplenishAdviceQtySum).subAggregation(addProductNumSum)
.subAggregation(manualReplenishProductNumSum).subAggregation(aiReplenishProductNumSum).subAggregation(specialReplenishProductNumDqSum).subAggregation(specialReplenishProductNumTgSum)
.subAggregation(specialReplenishProductNumYcSum).subAggregation(orderProductNumSum).subAggregation(orderQtySum).subAggregation(adviceReplenishProductNumSum));
// 添加合计聚合结果,与分组同一维度,不能加在上面subAggregation()中
searchSourceBuilder.aggregation(replenishAdviceQtySumBucket).aggregation(approveProductNumSumBucketAct).aggregation(actApproveQtySumBucket).aggregation(actReplenishProductNumSumBucket)
.aggregation(actReplenishAdviceQtySumBucket).aggregation(addProductNumSumBucket).aggregation(manualReplenishProductNumSumBucket).aggregation(aiReplenishProductNumSumBucket).aggregation(specialReplenishProductNumDqSumBucket)
.aggregation(specialReplenishProductNumTgSumBucket).aggregation(specialReplenishProductNumYcSumBucket).aggregation(orderProductNumSumBucket).aggregation(orderQtySumBucket).aggregation(adviceReplenishProductNumSumBucket);
}
取聚合统计后合计数据
/**
* 取聚合统计后合计,返回double
*
* @param totalMap
* @return
*/
public static ResFoodOrderInspectionTotalVO buildTotal(Map<String, Aggregation> totalMap) {
ResFoodOrderInspectionTotalVO vo = new ResFoodOrderInspectionTotalVO();
vo.setReplenishAdviceQtyTotal(new BigDecimal(String.valueOf(((ParsedSimpleValue) totalMap.get(FoodOrderInspectionConstant.REPLENISHADVICEQTYTOTAL)).value())).setScale(2, BigDecimal.ROUND_DOWN));
vo.setActApproveProductNumTotal(Integer.valueOf(new Double(((ParsedSimpleValue) totalMap.get(FoodOrderInspectionConstant.ACTAPPROVEPRODUCTNUMTOTAL)).value()).intValue()));
vo.setActApproveQtyTotal(new BigDecimal(String.valueOf(((ParsedSimpleValue) totalMap.get(FoodOrderInspectionConstant.ACTAPPROVEQTYTOTAL)).value())).setScale(2, BigDecimal.ROUND_DOWN));
vo.setActReplenishProductNumTotal(Integer.valueOf(new Double(((ParsedSimpleValue) totalMap.get(FoodOrderInspectionConstant.ACTREPLENISHPRODUCTNUMTOTAL)).value()).intValue()));
vo.setActReplenishAdviceQtyTotal(new BigDecimal(String.valueOf(((ParsedSimpleValue) totalMap.get(FoodOrderInspectionConstant.ACTREPLENISHADVICEQTYTOTAL)).value())).setScale(2, BigDecimal.ROUND_DOWN));
vo.setAddProductNumTotal(Integer.valueOf(new Double(((ParsedSimpleValue) totalMap.get(FoodOrderInspectionConstant.ADDPRODUCTNUMTOTAL)).value()).intValue()));
vo.setManualReplenishProductNumTotal(Integer.valueOf(new Double(((ParsedSimpleValue) totalMap.get(FoodOrderInspectionConstant.MANUALREPLENISHPRODUCTNUMTOTAL)).value()).intValue()));
vo.setAiReplenishProductNumTotal(Integer.valueOf(new Double(((ParsedSimpleValue) totalMap.get(FoodOrderInspectionConstant.AIREPLENISHPRODUCTNUMTOTAL)).value()).intValue()));
vo.setSpecialReplenishProductNumDqTotal(Integer.valueOf(new Double(((ParsedSimpleValue) totalMap.get(FoodOrderInspectionConstant.SPECIALREPLENISHPRODUCTNUMDQTOTAL)).value()).intValue()));
vo.setSpecialReplenishProductNumTgTotal(Integer.valueOf(new Double(((ParsedSimpleValue) totalMap.get(FoodOrderInspectionConstant.SPECIALREPLENISHPRODUCTNUMTGTOTAL)).value()).intValue()));
vo.setSpecialReplenishProductNumYcTotal(Integer.valueOf(new Double(((ParsedSimpleValue) totalMap.get(FoodOrderInspectionConstant.SPECIALREPLENISHPRODUCTNUMYCTOTAL)).value()).intValue()));
vo.setOrderProductNumTotal(Integer.valueOf(new Double(((ParsedSimpleValue) totalMap.get(FoodOrderInspectionConstant.ORDERPRODUCTNUMTOTAL)).value()).intValue()));
vo.setOrderQtyTotal(new BigDecimal(String.valueOf(((ParsedSimpleValue) totalMap.get(FoodOrderInspectionConstant.ORDERQTYTOTAL)).value())).setScale(2, BigDecimal.ROUND_DOWN));
vo.setAdviceReplenishProductNumTotal(Integer.valueOf(new Double(((ParsedSimpleValue) totalMap.get(FoodOrderInspectionConstant.ADVICEREPLENISHPRODUCTNUMTOTAL)).value()).intValue()));
return vo;
}
非聚合字段排序
/**
* 非聚合字段排序
*
* @param resList
* @param reqVO
*/
public void orderBy(List<ResFoodOrderInspectionVO> resList, ReqFoodOrderInspectionVO reqVO) {
if (!Stream.of(APPLYDATE_ORG_GROUP_LOCATION_FIELDS).collect(Collectors.toList()).contains(reqVO.getOrderBy())) {
return;
}
if (FoodOrderInspectionConstant.APPLYDATE.equals(reqVO.getOrderBy())) {
if (FoodOrderInspectionConstant.ASC.equals(reqVO.getSort())) {
resList.sort(Comparator.comparing(ResFoodOrderInspectionVO::getApplyDate));// 升序
} else {
resList.sort(Comparator.comparing(ResFoodOrderInspectionVO::getApplyDate).reversed());//降序
}
}
if (FoodOrderInspectionConstant.PURCHASEGROUPCODE.equals(reqVO.getOrderBy())) {
if (FoodOrderInspectionConstant.ASC.equals(reqVO.getSort())) {
resList.sort(Comparator.comparing(ResFoodOrderInspectionVO::getPurchaseGroupCode));
} else {
resList.sort(Comparator.comparing(ResFoodOrderInspectionVO::getPurchaseGroupCode).reversed());
}
}
if (FoodOrderInspectionConstant.PURCHASEORGCODE.equals(reqVO.getOrderBy())) {
if (FoodOrderInspectionConstant.ASC.equals(reqVO.getSort())) {
resList.sort(Comparator.comparing(ResFoodOrderInspectionVO::getPurchaseOrgCode));
} else {
resList.sort(Comparator.comparing(ResFoodOrderInspectionVO::getPurchaseOrgCode).reversed());
}
}
if (CollectionUtils.isNotEmpty(reqVO.getLocationCodes()) && FoodOrderInspectionConstant.LOCATIONCODE.equals(reqVO.getOrderBy())) {
if (FoodOrderInspectionConstant.ASC.equals(reqVO.getSort())) {
resList.sort(Comparator.comparing(ResFoodOrderInspectionVO::getLocationCode));
} else {
resList.sort(Comparator.comparing(ResFoodOrderInspectionVO::getLocationCode).reversed());
}
}
// 百分比排序
if (FoodOrderInspectionConstant.REPLENISHACCEPTPERCENT.equals(reqVO.getOrderBy())) {
if (FoodOrderInspectionConstant.ASC.equals(reqVO.getSort())) {
resList.sort(Comparator.comparing(ResFoodOrderInspectionVO::getReplenishAcceptPercent));
} else {
resList.sort(Comparator.comparing(ResFoodOrderInspectionVO::getReplenishAcceptPercent).reversed());
}
}
if (FoodOrderInspectionConstant.ADDREPLENISHPERCENT.equals(reqVO.getOrderBy())) {
if (FoodOrderInspectionConstant.ASC.equals(reqVO.getSort())) {
resList.sort(Comparator.comparing(ResFoodOrderInspectionVO::getAddReplenishPercent));
} else {
resList.sort(Comparator.comparing(ResFoodOrderInspectionVO::getAddReplenishPercent).reversed());
}
}
if (FoodOrderInspectionConstant.MANUALREPLENISHPERCENT.equals(reqVO.getOrderBy())) {
if (FoodOrderInspectionConstant.ASC.equals(reqVO.getSort())) {
resList.sort(Comparator.comparing(ResFoodOrderInspectionVO::getManualReplenishPercent));
} else {
resList.sort(Comparator.comparing(ResFoodOrderInspectionVO::getManualReplenishPercent).reversed());
}
}
if (FoodOrderInspectionConstant.AIREPLENISHPERCENT.equals(reqVO.getOrderBy())) {
if (FoodOrderInspectionConstant.ASC.equals(reqVO.getSort())) {
resList.sort(Comparator.comparing(ResFoodOrderInspectionVO::getAiReplenishPercent));
} else {
resList.sort(Comparator.comparing(ResFoodOrderInspectionVO::getAiReplenishPercent).reversed());
}
}
if (FoodOrderInspectionConstant.SPECIALREPLENISHPERCENT.equals(reqVO.getOrderBy())) {
if (FoodOrderInspectionConstant.ASC.equals(reqVO.getSort())) {
resList.sort(Comparator.comparing(ResFoodOrderInspectionVO::getSpecialReplenishPercent));
} else {
resList.sort(Comparator.comparing(ResFoodOrderInspectionVO::getSpecialReplenishPercent).reversed());
}
}
if (FoodOrderInspectionConstant.QTYUPDATEPERCENT.equals(reqVO.getOrderBy())) {
if (FoodOrderInspectionConstant.ASC.equals(reqVO.getSort())) {
resList.sort(Comparator.comparing(ResFoodOrderInspectionVO::getQtyUpdatePercent));
} else {
resList.sort(Comparator.comparing(ResFoodOrderInspectionVO::getQtyUpdatePercent).reversed());
}
}
if (FoodOrderInspectionConstant.PRODUCTUPDATEPERCENT.equals(reqVO.getOrderBy())) {
if (FoodOrderInspectionConstant.ASC.equals(reqVO.getSort())) {
resList.sort(Comparator.comparing(ResFoodOrderInspectionVO::getProductUpdatePercent));
} else {
resList.sort(Comparator.comparing(ResFoodOrderInspectionVO::getProductUpdatePercent).reversed());
}
}
}
伪分页
/**
* 伪分页实现
*
* @param list
* @param pageNum
* @param pageSize
* @param <T>
* @return
*/
public <T> List<T> pageHandle(List<T> list, int pageNum, int pageSize) {
int fromIndex = (pageNum - 1) * pageSize;
int toIndex = pageNum * pageSize;
int maxIndex = list.size();
fromIndex = fromIndex >= 0 ? fromIndex : 0;
toIndex = toIndex <= maxIndex ? toIndex : maxIndex;
if (fromIndex > toIndex) {
fromIndex = 1;
}
return list.subList(fromIndex, toIndex);
}
文章浏览阅读3.4k次,点赞8次,收藏42次。一、什么是内部类?or 内部类的概念内部类是定义在另一个类中的类;下面类TestB是类TestA的内部类。即内部类对象引用了实例化该内部对象的外围类对象。public class TestA{ class TestB {}}二、 为什么需要内部类?or 内部类有什么作用?1、 内部类方法可以访问该类定义所在的作用域中的数据,包括私有数据。2、内部类可以对同一个包中的其他类隐藏起来。3、 当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷。三、 内部类的分类成员内部_成员内部类和局部内部类的区别
文章浏览阅读118次。分布式系统要求拆分分布式思想的实质搭配要求分布式系统要求按照某些特定的规则将项目进行拆分。如果将一个项目的所有模板功能都写到一起,当某个模块出现问题时将直接导致整个服务器出现问题。拆分按照业务拆分为不同的服务器,有效的降低系统架构的耦合性在业务拆分的基础上可按照代码层级进行拆分(view、controller、service、pojo)分布式思想的实质分布式思想的实质是为了系统的..._分布式系统运维工具
文章浏览阅读174次。1.数据源准备2.数据处理step1:数据表处理应用函数:①VLOOKUP函数; ② CONCATENATE函数终表:step2:数据透视表统计分析(1) 透视表汇总不同渠道用户数, 金额(2)透视表汇总不同日期购买用户数,金额(3)透视表汇总不同用户购买订单数,金额step3:讲第二步结果可视化, 比如, 柱形图(1)不同渠道用户数, 金额(2)不同日期..._exce l趋势分析数据量
文章浏览阅读3.3k次。堡垒机可以为企业实现服务器、网络设备、数据库、安全设备等的集中管控和安全可靠运行,帮助IT运维人员提高工作效率。通俗来说,就是用来控制哪些人可以登录哪些资产(事先防范和事中控制),以及录像记录登录资产后做了什么事情(事后溯源)。由于堡垒机内部保存着企业所有的设备资产和权限关系,是企业内部信息安全的重要一环。但目前出现的以下问题产生了很大安全隐患:密码设置过于简单,容易被暴力破解;为方便记忆,设置统一的密码,一旦单点被破,极易引发全面危机。在单一的静态密码验证机制下,登录密码是堡垒机安全的唯一_horizon宁盾双因素配置
文章浏览阅读7.7k次,点赞4次,收藏16次。Chrome作为一款挺不错的浏览器,其有着诸多的优良特性,并且支持跨平台。其支持(Windows、Linux、Mac OS X、BSD、Android),在绝大多数情况下,其的安装都很简单,但有时会由于网络原因,无法安装,所以在这里总结下Chrome的安装。Windows下的安装:在线安装:离线安装:Linux下的安装:在线安装:离线安装:..._chrome linux debian离线安装依赖
文章浏览阅读153次。中国发达城市榜单每天都在刷新,但无非是北上广轮流坐庄。北京拥有最顶尖的文化资源,上海是“摩登”的国际化大都市,广州是活力四射的千年商都。GDP和发展潜力是衡量城市的数字指...
文章浏览阅读3.3k次。前言spark在java使用比较少,多是scala的用法,我这里介绍一下我在项目中使用的代码配置详细算法的使用请点击我主页列表查看版本jar版本说明spark3.0.1scala2.12这个版本注意和spark版本对应,只是为了引jar包springboot版本2.3.2.RELEASEmaven<!-- spark --> <dependency> <gro_使用java调用spark注册进去的程序
文章浏览阅读4.8k次。汽车零部件开发工具巨头V公司全套bootloader中UDS协议栈源代码,自己完成底层外设驱动开发后,集成即可使用,代码精简高效,大厂出品有量产保证。:139800617636213023darcy169_uds协议栈 源代码
文章浏览阅读4.6k次,点赞20次,收藏148次。AUTOSAR基础篇之OS(下)前言首先,请问大家几个小小的问题,你清楚:你知道多核OS在什么场景下使用吗?多核系统OS又是如何协同启动或者关闭的呢?AUTOSAR OS存在哪些功能安全等方面的要求呢?多核OS之间的启动关闭与单核相比又存在哪些异同呢?。。。。。。今天,我们来一起探索并回答这些问题。为了便于大家理解,以下是本文的主题大纲:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JCXrdI0k-1636287756923)(https://gite_autosar 定义了 5 种多核支持类型
文章浏览阅读2.2k次,点赞6次,收藏14次。原因:自己写的头文件没有被加入到方案的包含目录中去,无法被检索到,也就无法打开。将自己写的头文件都放入header files。然后在VS界面上,右键方案名,点击属性。将自己头文件夹的目录添加进去。_vs2013打不开自己定义的头文件
文章浏览阅读3.3w次,点赞80次,收藏342次。此时,可以将系统中所有用户的 Session 数据全部保存到 Redis 中,用户在提交新的请求后,系统先从Redis 中查找相应的Session 数据,如果存在,则再进行相关操作,否则跳转到登录页面。此时,可以将系统中所有用户的 Session 数据全部保存到 Redis 中,用户在提交新的请求后,系统先从Redis 中查找相应的Session 数据,如果存在,则再进行相关操作,否则跳转到登录页面。当数据量很大时,count 的数量的指定可能会不起作用,Redis 会自动调整每次的遍历数目。_redis命令
文章浏览阅读449次,点赞3次,收藏3次。URP的设计目标是在保持高性能的同时,提供更多的渲染功能和自定义选项。与普通项目相比,会多出Presets文件夹,里面包含着一些设置,包括本色,声音,法线,贴图等设置。全局只有主光源和附加光源,主光源只支持平行光,附加光源数量有限制,主光源和附加光源在一次Pass中可以一起着色。URP:全局只有主光源和附加光源,主光源只支持平行光,附加光源数量有限制,一次Pass可以计算多个光源。可编程渲染管线:渲染策略是可以供程序员定制的,可以定制的有:光照计算和光源,深度测试,摄像机光照烘焙,后期处理策略等等。_urp渲染管线