目录
一、springboot使用聚合方法处理业务查询排序心得
二、分页代码
三、对二中condSortParam参数进行加工后的程序
五、总结
一、springboot使用聚合方法处理业务查询排序心得
- 思路。此文编程部分思路大部分通过文心一言(免费版本即可) 获取。
注意:但在首次使用所给的答案绕了远路,第二回通过给他发送明确的内容做基础,如发送 mongosh脚本后 给出了编码 才拿到正确的解答方式
注意:在springboot中使用正确的方式编程,springboot中使用aggregate方法与使用mongosh 脚本基本方法名称相同, 不然会出现问题(奇怪的问题)
- 如下是提的问题。询问文心一言内容
-
注意首先编写mongosh脚本进行查询。查询结果正确后。询问文心一言获取springboot的编程代码
如:
shelldb.document.aggregate([{ $addFields: { sortOrder: { $cond: { if: { $eq: ["$status", "8"] }, then: 1, else: { $cond:{ if: { $eq: ["$status", "9"] },then: 2, else: -1 } } } } } }, { $sort: { sortOrder: -1, applyTime: -1 } },{ $project: { _id: 1, accNum: 1, status: 1, applyTime: 1 } } ]);将上述脚本 用springboot 编程实现
二、分页代码
-
注意:此代码为分页方法,传入的CondSortParam是经过加工后传入的,带有mongo聚合查询需要的AggregationOperation与SortOperation
-
注意:Aggregation.newAggregation中 AggregationOperation参数的排列顺序会影像查询结果
例如:
排序1
查询结果会先排序后通过条件进行处理。
SortOpertion, AddFieldsOpertion.....
解决方法:倒置:AddFieldsOpertion, SortOpertion...
java/* * 分页公共方法 */ public static <T> PageVO<T> pagination(PageRequestDTO dto, Class<T> tClass, MongoTemplate mongoTemplate, CondSortParam condSortParam) { # 获取查询条件 Criteria criteria = handleCriteria(dto); // 添加查询条件 MatchOperation matchOperation = Aggregation.match(criteria); // 计算总数, 分页 Query query = new Query(); query.addCriteria(criteria); if (!ObjectUtils.allNotNull(dto.getCurrentPageNum())) { dto.setCurrentPageNum(0); } if (!ObjectUtils.allNotNull(dto.getSize())) { dto.setSize(10); } long count = mongoTemplate.count(query, tClass); log.info("统计sql: {}", query); int offset = (dto.getCurrentPageNum() - 1) * dto.getSize(); # 分页条件处理 SkipOperation skipOperation = Aggregation.skip(offset); LimitOperation limitOperation = Aggregation.limit(dto.getSize()); Aggregation aggregation = null; List<AggregationOperation> list = new ArrayList<>(); if(condSortParam != null) { list.add(matchOperation); # 此处为【添加字段】条件集合 condSortParam.getAddFieldsOperations().forEach(s-> list.add(s)); if(condSortParam.getSortOperation() != null) { list.add(condSortParam.getSortOperation()); } list.add(skipOperation); list.add(limitOperation); aggregation = Aggregation.newAggregation(list); } log.info("分页查询sql: {}", aggregation); List<T> results = mongoTemplate.aggregate(aggregation, tClass, tClass).getMappedResults(); PageVO<T> pageVO = new PageVO<T>(); pageVO.setTotalNum(count); pageVO.setResults(results); return pageVO; } /* * 处理查询条件 */ private static Criteria handleCriteria(PageRequestDTO dto) { List<ParamDTO> params = dto.getParams(); Criteria criteria = new Criteria(); if(CollUtil.isEmpty(params)) return criteria; params.forEach(param -> { String operator = param.getOperator(); switch (operator) { case "eq" -> criteria.and(param.getField()).is(param.getFieldValue()); case "like" -> criteria.and(param.getField()).regex(Pattern.compile("^.*" + param.getFieldValue() + ".*$", Pattern.CASE_INSENSITIVE)); case "le" -> criteria.and(param.getField()).lt(param.getFieldValue()); case "ge" -> criteria.and(param.getField()).gt(param.getFieldValue()); case "in" -> { List<String> values = null; if (param.getFieldValue() instanceof JSONArray) { JSON.parseArray(param.getFieldValue().toString(), String.class); criteria.and(param.getField()).in(values); }else if(param.getFieldValue() instanceof String){ criteria.and(param.getField()).in(param.getFieldValue().toString().split(StrUtil.COMMA)); } } case "between" -> { if (param.getFieldValue() instanceof JSONArray) { List<Object> list = JSON.parseArray(param.getFieldValue().toString(), Object.class); if (CollUtil.isNotEmpty(list)) { criteria.and(param.getField()).gte(list.get(0)).lte(list.get(1)); } } } default -> { } } }); return criteria; }
三、对二中condSortParam参数进行加工后的程序
- AggregationOperation加工方法
注意:此处使用switch应对业务场景创建,不同case的处理operation的复杂度不同
较复杂case:添加了两个字段的判断
代码case上已标注
简单case:只添加了一个字段的判断
代码case上已标注
java
/*
* 获取聚合函数所需参数
*/
public static DataToolUtil.CondSortParam createDCondSortParamByPageType(String pageType) {
String [] codes;
String addSortFieldName = "statusOrder";
String sortFieldName = "status";
AtomicInteger level = new AtomicInteger();
SortOperation sortOperation;
switch (pageType) {
# 简单case
case D_STATUS.TYPE_APPLY:
codes = new String[]{D_STATUS.APPLY_REJECT.getCode(), D_STATUS.AUDITED_PRINTED.getCode(), D_STATUS.AUDITED.getCode()
, D_STATUS.APPLY.getCode(), D_STATUS.APPLY_REVOKE.getCode(), D_STATUS.SUBMIT.getCode()
, D_STATUS.REPORT_REJECT.getCode(), D_STATUS.REVOKE_AUDITED.getCode(), D_STATUS.REVOKE.getCode()
, D_STATUS.REPORT_DRAFT.getCode(), D_STATUS.DATA_DESTRY.getCode()
};
sortOperation = Aggregation.sort(Sort.Direction.DESC, addSortFieldName, "applyTime");
return new DataToolUtil.CondSortParam.Builder()
.addFieldOperation(createCondSortParamByPageType(sortFieldName, codes, level, addSortFieldName))
.addSortOperation(sortOperation)
.build();
# 简单case
case D_STATUS.TYPE_REPORT:
codes = new String[]{D_STATUS.REPORT_REJECT.getCode(), D_STATUS.REVOKE.getCode(), D_STATUS.REPORT_DRAFT.getCode()
, D_STATUS.APPLY.getCode(), D_STATUS.APPLY_REJECT.getCode()
};
sortOperation = Aggregation.sort(Sort.Direction.DESC, addSortFieldName, "applyTime");
return new DataToolUtil.CondSortParam.Builder()
.addFieldOperation(createCondSortParamByPageType(sortFieldName, codes, level, addSortFieldName))
.addSortOperation(sortOperation)
.build();
# 复杂case, 添加了两个AddSortFieldName
case D_STATUS.TYPE_AUDIT:
DataToolUtil.RelationWrapper statusWrapper = DataToolUtil.RelationWrapper.builder()
.addSortFieldName(addSortFieldName).sortFieldname(sortFieldName).build();
DataToolUtil.RelationWrapper pati..Wrapper = DataToolUtil.RelationWrapper.builder()
.addSortFieldName("pati....ypeIdOrder").sortFieldname("pati....ypeId").build();
codes = new String[]{D_STATUS.REVOKE.getCode(), D_STATUS.SUBMIT.getCode(), D_STATUS.AUDITED.getCode(), D_STATUS.AUDITED_PRINTED.getCode()};
sortOperation = Aggregation.sort(Sort.Direction.DESC, pati..Wrapper.getAddSortFieldName()).and(Sort.by(Sort.Direction.DESC, statusWrapper.getAddSortFieldName(), "app...ime"));
return new DataToolUtil.CondSortParam.Builder()
.addFieldOperation(createCondSortParamByPageType(statusWrapper.getSortFieldname(), codes, level, statusWrapper.getAddSortFieldName()))
.addFieldOperation(createCondSortParamByPageType(pati..Wrapper.getSortFieldname(), new String[]{PATIENT_TYPE.EMERGENCY.getCode()}, level, pati..Wrapper.getAddSortFieldName()))
.addSortOperation(sortOperation)
.build();
default:
return null;
}
}
/**
* 分页排序公共参数。
* 带条件排序字段与排序字段的排列顺序
*/
@Data
@Builder
public static class CondSortParam{
/** 提供的AggregationOperation */
List<AddFieldsOperation> addFieldsOperations;
/** 组合排序字段。如 Aggregation.sort(Direction.DESC, "sortOrder", "applyTime") */
SortOperation sortOperation;
public static class Builder {
private CondSortParam condSortParam = CondSortParam.builder().build();
public Builder() {
this.condSortParam.addFieldsOperations = new ArrayList<>();
}
public Builder addFieldOperation(AddFieldsOperation addFieldsOperation) {
this.condSortParam.addFieldsOperations.add(addFieldsOperation);
return this;
}
public Builder addSortOperation(SortOperation sortOperation) {
this.condSortParam.sortOperation = sortOperation;
return this;
}
public CondSortParam build() {
return this.condSortParam;
}
}
}
/*
* 绑定排序时需要条件判断而添加的字段名称与原字段名称
*/
@Data
@lombok.Builder
public static class RelationWrapper {
/** 增加的字段,拍寻优先级使用 */
private String addSortFieldName;
/** 需要被排序的字段, 条件判断使用 */
private String sortFieldname;
}
- 入口调用方法
java
@Operation(summary = "列表查询", parameters = {
@Parameter(name = "pageRequest", description = "...", required = true)
})
@PostMapping("queryPage")
public CommonJsonResponseVO queryPage(@RequestBody PageRequestDTO pageRequest) {
...
PageVO<RemoteDiagnosis> pageVO = DataToolUtil.pagination(pageRequest, RemoteDiagnosis.class, mongoTemplate, Status.createDiagCondSortParamByPageType(pageRequest.getPageType()));
return CommonJsonResponseVO.success(PageUtil.toPage(pageVO.getResults(), pageVO.getTotalNum()));
}
总结
- 复杂排序的完成需要从简单的排序入手。逐渐增加复杂度将有路可循。
- AI的正确使用会提高成功效率。只是凭借以往的查询方式(如百度查询等)无法深入挖掘一个工具的使用方法,比较困难。
- 对象化的参数会对复杂的排序提高可读性、易用性。
如:RelationWrapper 对参数进行抽象