相较于
https://blog.csdn.net/hanjun0612/article/details/121972663?spm=1001.2014.3001.5501
这次添加了更多的指令
一,反射类
package com.leadtrans.report.common; import org.springframework.aop.support.AopUtils; import org.springframework.context.ApplicationContext; import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.math.BigDecimal; import java.util.*; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; /** * @author: Tyler * @createDate: 2021/12/9 */ public class ReflectionUtil { /** * 调用示例 * public ApiResponse<String> test() throws Exception { * Class[] argsType=new Class[]{Class.forName("java.lang.String")}; * Object[] args=new Object[]{"hello"}; * ReflectionUtil.invokeMethod(new ReportImpl(),"Test",argsType,args); * return new ApiResponse().Success("str"); * } * @param owner 类的实例 * @param methodName 方法名 * @param argsClass 参数类型 * @param args 参数 * @return * @throws Exception */ public static Object invokeMethod(Object owner,String methodName,Class[] argsClass,Object[] args) throws Exception{ Object objRtn=null; Class ownerClass = owner.getClass(); Method method = ownerClass.getMethod(methodName, argsClass); objRtn = method.invoke(owner, args); return objRtn; } public static Field getFiled(Object obj,String filedName){ Field field=null; try { field = obj.getClass().getDeclaredField(filedName); field.setAccessible(true); } catch (NoSuchFieldException e) { e.printStackTrace(); } finally { return field; } } public static Object getFiledValue(Object obj,String filedName){ Object objValue=null; try { Field field = getFiled(obj,filedName); objValue = field.get(obj); }catch (IllegalAccessException e) { e.printStackTrace(); } finally { return objValue; } } }
二,动态lambda
Filter
/** * Lambda 动态 Filter * * @param list 数据 * @param equalsMap contains 过滤器 * @param notEqualsMap !contains 过滤器 * @param <T> * @return */ public <T> List<T> getDataListFilter(List<T> list, Map<String, List<Object>> equalsMap, Map<String, List<Object>> notEqualsMap,Map<String, List<Object>> containsMap, Map<String, Integer> dateLessMap, Map<String, List<Object>> startWithMap, Map<String, List<Object>> notStartWithMap) { //相等 LambdaFilter equalsFilter = new EqualsFilter(); list = equalsFilter.filer(list, equalsMap); //不等 LambdaFilter notEqualsFilter = new NotEqualsFilter(); list = notEqualsFilter.filer(list, notEqualsMap); //包含 LambdaFilter containsFilter=new ContainsFilter(); list = containsFilter.filer(list,containsMap); //时间小于 LambdaBaseFilter dateLessFilter = new DateLessFilter(); list = dateLessFilter.filer(list, dateLessMap); //前缀相同 LambdaFilter startWithFilter = new StartWithFilter(); list = startWithFilter.filer(list, startWithMap); //前缀不同 LambdaFilter notStartWithFilter = new NotStartWithFilter(); list = notStartWithFilter.filer(list, notStartWithMap); List<T> rList = list; return rList; }
过滤类:
1,base接口
public interface LambdaBaseFilter<T,U> { List<T> filer(List<T> st, Map<String, U> map); }
2,接口
public interface LambdaFilter<T> extends LambdaBaseFilter<T,List<Object>> { List<T> filer(List<T> st, Map<String, List<Object>> map); }
3,EqualsFilter
package com.leadtrans.report.common.lambdaReport.filter; import com.leadtrans.report.common.ReflectionUtil; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * @author: Tyler * @createDate: 2022/1/13 */ /** * 需要过滤的相等字段 * "equalsMap": {"mode": ["FCL","BCN"],"importOrExport": ["Export","Other"]}, * 筛选 mode等于FCL或BCN,并且importOrExport等于Export或Other * @param <T> */ public class EqualsFilter<T> implements LambdaFilter<T> { @Override public List<T> filer(List<T> st, Map<String, List<Object>> map) { if (map != null) { for (Map.Entry<String, List<Object>> item : map.entrySet()) { st = st.stream() .filter(x -> item.getValue().contains( ReflectionUtil.getFiledValue(x, item.getKey()) == null ? "null" : ReflectionUtil.getFiledValue(x, item.getKey())) ) .collect(Collectors.toList()); } } return st; } }
4,NotEqualsFilter
package com.leadtrans.report.common.lambdaReport.filter; import com.leadtrans.report.common.ReflectionUtil; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * @author: Tyler * @createDate: 2022/1/13 */ /** * 需要过滤的不等字段 * "notEqualsMap": {"invoiceStatus": ["WHL","OTHER"]}, * 筛选invoiceStatus不等于WHL或OTHER * @param <T> */ public class NotEqualsFilter<T> implements LambdaFilter<T> { @Override public List<T> filer(List<T> st, Map<String, List<Object>> notEqualsMap) { if (notEqualsMap != null) { for (Map.Entry<String, List<Object>> item : notEqualsMap.entrySet()) { st = st.stream() .filter(x -> !item.getValue().contains( ReflectionUtil.getFiledValue(x, item.getKey()) == null ? "null" : ReflectionUtil.getFiledValue(x, item.getKey())) ) .collect(Collectors.toList()); } } return st; } }
5,ContainsFilter
package com.leadtrans.report.common.lambdaReport.filter; import com.leadtrans.report.common.ReflectionUtil; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * @author: Tyler * @createDate: 2022/1/25 */ /** * 包含过滤器 * "containsMap": {"OSOCCreditor": ["SHALEASHA"]}, * 筛选 OSOCCreditor 包含SHALEASHA * @param <T> */ public class ContainsFilter<T> implements LambdaFilter<T> { @Override public List<T> filer(List<T> st, Map<String, List<Object>> map) { if (map != null) { for (Map.Entry<String, List<Object>> item : map.entrySet()) { for (Object it : item.getValue()) { st = st.stream() .filter(x -> (ReflectionUtil.getFiledValue(x, item.getKey()) == null ? "" : ReflectionUtil.getFiledValue(x, item.getKey()).toString() ) .contains(it.toString()) ) .collect(Collectors.toList()); } } } return st; } }
6,DateLessFilter
package com.leadtrans.report.common.lambdaReport.filter; import com.leadtrans.report.common.DateUtils; import com.leadtrans.report.common.ReflectionUtil; import org.apache.commons.lang3.StringUtils; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * @author: Tyler * @createDate: 2022/1/13 */ /** * 日期过滤 * "dateLessMap":{"jw_ATD": 5} * 筛选jw_ATD增加5天后,小于当天的数据 * @param <T> */ public class DateLessFilter<T> implements LambdaBaseFilter<T,Integer> { @Override public List<T> filer(List<T> st, Map<String, Integer> map) { if (map != null) { for (Map.Entry<String, Integer> item : map.entrySet()) { st = st.stream() .filter(x -> { Object colVal = ReflectionUtil.getFiledValue(x, item.getKey()); if (colVal != null && StringUtils.isNotBlank(colVal.toString())) { colVal = DateUtils.add(DateUtils.parse2(colVal.toString()), Calendar.DATE, item.getValue()); return new Date().after((Date) colVal); } return false; }) .collect(Collectors.toList()); } } return st; } }
7,StartWithFilter
package com.leadtrans.report.common.lambdaReport.filter; import com.leadtrans.report.common.ReflectionUtil; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * @author: Tyler * @createDate: 2022/1/13 */ /** * 前缀包含 * "startWithMap":{"country":["CN"]} * 筛选 前缀为CN开头的 * @param <T> */ public class StartWithFilter<T> implements LambdaFilter<T> { @Override public List<T> filer(List<T> st, Map<String, List<Object>> map) { if (map != null) { List<T> stResult=new ArrayList<>(); for (Map.Entry<String, List<Object>> item : map.entrySet()) { for (Object it : item.getValue()) { st = st.stream() .filter(x -> (ReflectionUtil.getFiledValue(x, item.getKey()) == null ? "" : ReflectionUtil.getFiledValue(x, item.getKey()).toString() ) .startsWith(it.toString()) ) .collect(Collectors.toList()); stResult.addAll(st); } } return stResult; } else { return st; } } }
8,NotStartWithFilter
package com.leadtrans.report.common.lambdaReport.filter; import com.leadtrans.report.common.ReflectionUtil; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * @author: Tyler * @createDate: 2022/1/13 */ /** * 前缀过滤 * "notStartWithMap": {"houseBill": ["W"]}, * 筛选houseBill不以W开头 * @param <T> */ public class NotStartWithFilter<T> implements LambdaFilter<T> { @Override public List<T> filer(List<T> st, Map<String, List<Object>> map) { if (map != null) { for (Map.Entry<String, List<Object>> item : map.entrySet()) { for (Object it : item.getValue()) { st = st.stream() .filter(x -> !(ReflectionUtil.getFiledValue(x, item.getKey()) == null ? "" : ReflectionUtil.getFiledValue(x, item.getKey()).toString() ) .startsWith(it.toString()) ) .collect(Collectors.toList()); } } } return st; } }
Group
/** * Lambda 动态 Group * * @param list 数据 * @param fieldGroups 聚合字段 * @param <T> * @return */ public <T> Map<String, List<T>> getDataListGroup(List<T> list, List<String> fieldGroups) { Map<String, List<T>> map = list.stream().collect(Collectors.groupingBy(x -> { String groupItem = ""; for (String y : fieldGroups) { groupItem += ReflectionUtil.getFiledValue(x, y) + "_"; } return groupItem; })); return map; }
Calculate 计算命令
CalCulate 计算
/** * 输出数据 * * @param dataList 数据源 * @param fieldNames 属性名 * @param calculateNames 需要计算的列 * @return */ public <T> List<List<Object>> getDataList(Map<String, List<T>> dataList, List<String> fieldNames, List<String> calculateNames) { List<List<Object>> data = new ArrayList<>(); for (Map.Entry<String, List<T>> entry : dataList.entrySet()) { List<Object> obj = new ArrayList<>(); for (String colName : fieldNames) { //普通字段 if (!calculateNames.contains(colName)) { LambdaCalculate lambdaCalculate = new NotCalculate(); Object colVal = lambdaCalculate.calculate(entry.getKey(), entry.getValue(), colName); obj.add(colVal); } //计算count 标签 else if (colName.toLowerCase().replace(" ", "").startsWith("count(".toLowerCase())) { LambdaCalculate lambdaCalculate = new CountCalculate(); Object colVal = lambdaCalculate.calculate(entry.getValue(), colName); obj.add(colVal); } //计算countDistinct标签 else if (colName.toLowerCase().replace(" ", "").startsWith("countDistinct(".toLowerCase())) { LambdaCalculate lambdaCalculate = new CountDistinctCalculate(); Object colVal = lambdaCalculate.calculate(entry.getValue(), colName); obj.add(colVal); } //计算sum 标签 else if (colName.toLowerCase().replace(" ", "").startsWith("sum(".toLowerCase())) { LambdaCalculate lambdaCalculate = new SumCalculate(); Object colVal = lambdaCalculate.calculate(entry.getValue(), colName); obj.add(colVal); } //计算列 else { LambdaCalculate lambdaCalculate = new NormalCalculate(); Object colVal = lambdaCalculate.calculate(entry.getValue(), colName); obj.add(colVal); } } //添加到data data.add(obj); } //默认按照第一列排序 data.sort(comparing(x -> (x.get(0) == null ? "" : x.get(0).toString()))); return data; }
接口:
public interface LambdaCalculate<T> { default Object calculate(List<T> list, String colName){ return calculate(null,list,colName); } Object calculate(Object key,List<T> list,String colName); }
1,NotCalculate
package com.leadtrans.report.common.lambdaReport.calculateTag; import com.leadtrans.report.common.DateUtils; import com.leadtrans.report.common.ReflectionUtil; import org.apache.commons.lang3.StringUtils; import java.util.Calendar; import java.util.List; /** * @author: Tyler * @createDate: 2022/1/14 */ /** * 无需计算 * 假设使用addDate(xxx,5) 则表示xxx增加5天 * 其他属性则直接展示 * @param <T> */ public class NotCalculate<T> implements LambdaCalculate<T> { @Override public Object calculate(Object key, List<T> list, String colName) { Object colVal=null; //addDate if (colName.toLowerCase().replace(" ", "").startsWith("addDate(".toLowerCase())) { String addDateName = colName.substring("addDate(".length(), colName.indexOf(")")); String[] args = addDateName.split(","); colVal = ReflectionUtil.getFiledValue(list.get(0), args[1]); if (colVal != null && StringUtils.isNotBlank(colVal.toString())) { colVal = DateUtils.toDateString(DateUtils.add(DateUtils.parse2(colVal.toString()), Calendar.DATE, Integer.parseInt(args[0])), "yyyy-MM-dd"); } } else { //判断属性是否存在 Object col = ReflectionUtil.getFiled(list.get(0), colName); if (col == null) { col=key; } else { //属性存在,则取值 colVal = ReflectionUtil.getFiledValue(list.get(0), colName); } } return colVal; } }
2,NormalCalculate
package com.leadtrans.report.common.lambdaReport.calculateTag; import com.leadtrans.report.common.ReflectionUtil; import java.math.BigDecimal; import java.util.List; /** * @author: Tyler * @createDate: 2022/1/14 */ /** * xxx 计算器 * 按照某一列,计算数值 * @param <T> */ public class NormalCalculate<T> implements LambdaCalculate<T>{ @Override public Object calculate(Object key, List<T> list, String colName) { Object colVal = list.stream() .map(x -> new BigDecimal(ReflectionUtil.getFiledValue(x, colName) == null ? "0" : ReflectionUtil.getFiledValue(x, colName).toString().replace(",", ""))) .reduce(BigDecimal.ZERO, BigDecimal::add); return colVal; } }
3,CountCalculate
package com.leadtrans.report.common.lambdaReport.calculateTag; import com.leadtrans.report.common.ReflectionUtil; import java.util.List; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; /** * @author: Tyler * @createDate: 2022/1/14 */ /** * count(xxx) 计算器 * 按照某一列,计算总数 * @param <T> */ public class CountCalculate<T> implements LambdaCalculate<T> { @Override public Object calculate(Object key, List<T> list, String colName) { Object colVal=null; String countName = colName.substring("count(".length(), colName.indexOf(")")); String[] args = countName.split(","); //如果args>1,说明有条件 if (args.length > 1) { //获取多个条件 String[] argsArr = args[0].split("&"); Supplier<Stream<T>> st = () -> list.stream(); for (String argsSimple : argsArr) { Supplier<Stream<T>> stFilter = st; //获取单个条件,拼接 String[] argsKV; if (argsSimple.indexOf("!:") > 0) { //不等 argsKV = argsSimple.split("!:"); st = () -> stFilter.get() .filter(x -> !argsKV[1].contains(ReflectionUtil.getFiledValue(x, argsKV[0]) == null ? "null" : ReflectionUtil.getFiledValue(x, argsKV[0]).toString())); } else { //相等 argsKV = argsSimple.split(":"); st = () -> stFilter.get() .filter(x -> argsKV[1].contains(ReflectionUtil.getFiledValue(x, argsKV[0]) == null ? "null" : ReflectionUtil.getFiledValue(x, argsKV[0]).toString())); } } colVal = st.get().collect(Collectors.toList()).size(); } else { colVal = list.size(); } return colVal; } }
4,CountDistinctCalculate
package com.leadtrans.report.common.lambdaReport.calculateTag; import com.leadtrans.report.common.ReflectionUtil; import java.util.ArrayList; import java.util.List; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; /** * @author: Tyler * @createDate: 2022/1/14 */ /** * countDistinct(xxx) 计算器 * 按照某一列,计算去重后总数 * @param <T> */ public class CountDistinctCalculate<T> implements LambdaCalculate<T> { @Override public Object calculate(Object key, List<T> list, String colName) { Object colVal=null; String countName = colName.substring("countDistinct(".length(), colName.indexOf(")")); String[] args = countName.split(","); //如果args>1,说明有条件 if (args.length > 1) { //获取多个and条件 String[] argsArr = args[0].split("&"); Supplier<Stream<T>> st = () -> (Stream<T>) list.stream(); for (String argsSimple : argsArr) { Supplier<Stream<T>> stFilter = st; //获取单个条件,拼接 String[] argsKV; //不等 if (argsSimple.indexOf("!:") > 0) { argsKV = argsSimple.split("!:"); st = () -> stFilter.get() .filter(x -> !argsKV[1].contains(ReflectionUtil.getFiledValue(x, argsKV[0]) == null ? "null" : ReflectionUtil.getFiledValue(x, argsKV[0]).toString())) ; } else { //相等 argsKV = argsSimple.split(":"); st = () -> stFilter.get() .filter(x -> argsKV[1].contains(ReflectionUtil.getFiledValue(x, argsKV[0]) == null ? "null" : ReflectionUtil.getFiledValue(x, argsKV[0]).toString())) ; } } colVal = st.get() .map(x -> ReflectionUtil.getFiledValue(x, args[1])) .distinct() .collect(Collectors.toList()).size(); } else { colVal = list.stream() .map(x -> ReflectionUtil.getFiledValue(x, args[0])) .distinct() .collect(Collectors.toList()).size(); } return colVal; } }
5,SumCalculate
package com.leadtrans.report.common.lambdaReport.calculateTag; import com.leadtrans.report.common.ReflectionUtil; import java.math.BigDecimal; import java.util.List; import java.util.function.Supplier; import java.util.stream.Stream; /** * @author: Tyler * @createDate: 2022/1/14 */ /** * sum(xxx) 计算器 * 按照某一列,计算总和 * @param <T> */ public class SumCalculate<T> implements LambdaCalculate<T>{ @Override public Object calculate(Object key, List<T> list, String colName) { Object colVal=null; String sumName = colName.substring("sum(".length(), colName.indexOf(")")); String[] args = sumName.split(","); //如果args>1,说明有条件 if (args.length > 1) { //获取多个条件 String[] argsArr = args[0].split("&"); Supplier<Stream<T>> st = () -> list.stream(); for (String argsSimple : argsArr) { Supplier<Stream<T>> stFilter = st; //获取单个条件,拼接 String[] argsKV; //不等 if (argsSimple.indexOf("!:") > 0) { argsKV = argsSimple.split("!:"); st = () -> stFilter.get() .filter(x -> !argsKV[1].contains(ReflectionUtil.getFiledValue(x, argsKV[0]) == null ? "null" : ReflectionUtil.getFiledValue(x, argsKV[0]).toString())); } else { //相等 argsKV = argsSimple.split(":"); st = () -> stFilter.get() .filter(x -> argsKV[1].contains(ReflectionUtil.getFiledValue(x, argsKV[0]) == null ? "null" : ReflectionUtil.getFiledValue(x, argsKV[0]).toString())); } } colVal = st.get() .map(x -> new BigDecimal(ReflectionUtil.getFiledValue(x, args[1]) == null ? "0" : ReflectionUtil.getFiledValue(x, args[1]).toString().replace(",", ""))) .reduce(BigDecimal.ZERO, BigDecimal::add); } else { colVal = list.stream() .map(x -> new BigDecimal(ReflectionUtil.getFiledValue(x, args[0]) == null ? "0" : ReflectionUtil.getFiledValue(x, args[0]).toString().replace(",", ""))) .reduce(BigDecimal.ZERO, BigDecimal::add); } return colVal; } }
总计列
/** * 添加合计列 * * @param fieldNames 字段 * @param data 数据 * @param calculateHeadsNames 计算列 * @return */ public List<Object> addTotal(List<String> fieldNames, List<List<Object>> data, List<String> calculateHeadsNames) { List<Object> totalLine = new ArrayList<>(); try { //按照数据的长度,初始化大小 if (data.size() > 0) { data.get(0).forEach(x -> totalLine.add("")); //增加TOTAL字样 totalLine.set(0, "TOTAL"); //计算列 if (calculateHeadsNames != null && calculateHeadsNames.size() > 0) { for (String colName : calculateHeadsNames) { Integer index = fieldNames.indexOf(colName); if (index > -1) { BigDecimal val = data.stream().map(x -> new BigDecimal(x.get(index) == null ? "0" : x.get(index).toString())) .reduce(BigDecimal::add).get(); totalLine.set(index, val); } } } } return totalLine; } catch (Exception e) { e.printStackTrace(); } finally { return totalLine; } }
三,测试
@Test public void testLambda() throws NoSuchFieldException, IllegalAccessException { List<MyTest> list=new ArrayList<>(); list.add(new MyTest(0,"n0","hobby0",1)); list.add(new MyTest(1,"n1","hobby1",1)); list.add(new MyTest(1,"n2","hobby2",1)); list.add(new MyTest(2,"n3","hobby3",1)); list.add(new MyTest(2,"n4","hobby4",1)); list.add(new MyTest(3,"n5","hobby5",1)); list.add(new MyTest(3,"n6","hobby6",1)); list.add(new MyTest(3,"n7","hobby7",1)); list.add(new MyTest(3,"n8","hobby7",1)); String json = FileUtil.readFile(System.getProperty("user.dir") + "/reportArgs"+"/myTest.json"); ReportArgsReq reportArgsReq= JSON.parseObject(json,ReportArgsReq.class); List<MyTest> rList = report.getDataListFilter(list, reportArgsReq.getEqualsMap(),reportArgsReq.getNotEqualsMap()); Map<String,List<MyTest>> rMap=report.getDataListGroup(rList,reportArgsReq.getFieldGroups()); System.out.println(rMap.size()); // List<FileTypeVO> rList=list.stream().filter(x->x.) }
MyTest.java
package com.leadtrans.report.model.DB; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import java.util.Date; /** * @author: Tyler * @createDate: 2021/12/7 */ @TableName(value = "myTest") public class MyTest { @TableId private Integer id; private String name; private String hobby; private Integer amount; public MyTest(){} public MyTest(Integer id,String name,String hobby,Integer amount){ this.id=id; this.name=name; this.hobby=hobby; this.amount=amount; } //get;set; }
myTest.json
{ "equalsMap": {}, "notEqualsMap": {}, "fieldGroups": ["id"], "headsExcel": ["id","name","hobby","amount sum"], "fieldNames": ["id","name","hobby","sum(amount)"], "calculateFieldNames": ["sum(amount)"] }
四,进阶
其实还有一些其他的用法。
样例:
{ "equalsMap": {"INCO": ["FOB","EXWORK"],"Test": ["a","b"]}, "notEqualsMap": {"Test1": ["hello"],"Test2": ["t1","t2"]}, "fieldGroups": ["pol","pod","jobName"], "headsExcel": ["jobName","pol","pod","INCO","TEU","AIR Bill","LCL Bill","jobProfit"], "fieldNames": ["jobName","pol","pod","INCO","sum(type:SEA&mode:FCL,TEU)","count(type:AIR,shipmentID)","count(mode:LCL,shipmentID)","jobProfit"], "calculateFieldNames": ["sum(type:SEA&mode:FCL,TEU)","count(type:AIR,shipmentID)","count(mode:LCL,shipmentID)","jobProfit"] }
解释:
字段 注释 equalsMap 需要过滤的相等字段。 notEqualsMap 需要过滤的不等字段。 startWithMap 前缀包含,以xxx开头 notStartWithMap 前缀过滤,不以xxx开头 dateLessMap 日期比较, "dateLessMap":{"jw_ATD": 5} 筛选出jw_ATD增加5天后,小于当天的数据 fieldTag 无需设置,备用字段。 目前用途: 1 动态字段拼接sql 2 两个报表根据某个字段进行 交集,差集,并集 fieldGroups 分组字段。 headsExcel 写入excel的表头 fieldNames 使用到的字段,对应到表头。 calculateFieldNames 需要计算的字段,int,decimal..... ( 匹配相等的合计 sum(type:SEA&mode:FCL,TEU) : 计算type为sea,并且mode为FCL 的TEU 总和 匹配相等的数量 count(type:AIR,shipmentID):计算type为Air,的shipment数量 匹配不等的合计 sum(type!:SEA&mode!:FCL,TEU) : 计算type不为sea,并且mode不为FCL 的TEU 总和 匹配不等的数量 count(type!:AIR,shipmentID):计算type不为Air,的shipment数量 合计 sum(jobProfit):计算jobProfit的总合 去重的数量 countDistinct(type:AIP,shipmentID):去重后计算count )