mongodb之使用聚合方法条件排序查询
目录
(图片来源网络,侵删)
一、springboot使用聚合方法处理业务查询排序心得
- 思路
- 提的问题
二、分页代码
三、对二中condSortParam参数进行加工后的程序
- AggregationOperation加工方法
- 入口调用方法
五、总结
一、springboot使用聚合方法处理业务查询排序心得
- 思路。此文编程部分思路大部分通过文心一言(免费版本即可) 获取。
注意:但在首次使用所给的答案绕了远路,第二回通过给他发送明确的内容做基础,如发送 mongosh脚本后 给出了编码 才拿到正确的解答方式
注意:在springboot中使用正确的方式编程,springboot中使用aggregate方法与使用mongosh 脚本基本方法名称相同, 不然会出现问题(奇怪的问题)
- 如下是提的问题。询问文心一言内容
- 注意首先编写mongosh脚本进行查询。查询结果正确后。询问文心一言获取springboot的编程代码
如:
db.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...
/* * 分页公共方法 */ public static PageVO pagination(PageRequestDTO dto, Class 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 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 results = mongoTemplate.aggregate(aggregation, tClass, tClass).getMappedResults(); PageVO pageVO = new PageVO(); pageVO.setTotalNum(count); pageVO.setResults(results); return pageVO; } /* * 处理查询条件 */ private static Criteria handleCriteria(PageRequestDTO dto) { List 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 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 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上已标注
/* * 获取聚合函数所需参数 */ 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 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; }
- 入口调用方法
@Operation(summary = "列表查询", parameters = { @Parameter(name = "pageRequest", description = "...", required = true) }) @PostMapping("queryPage") public CommonJsonResponseVO queryPage(@RequestBody PageRequestDTO pageRequest) { ... PageVO pageVO = DataToolUtil.pagination(pageRequest, RemoteDiagnosis.class, mongoTemplate, Status.createDiagCondSortParamByPageType(pageRequest.getPageType())); return CommonJsonResponseVO.success(PageUtil.toPage(pageVO.getResults(), pageVO.getTotalNum())); }
总结
- 复杂排序的完成需要从简单的排序入手。逐渐增加复杂度将有路可循。
- AI的正确使用会提高成功效率。只是凭借以往的查询方式(如百度查询等)无法深入挖掘一个工具的使用方法,比较困难。
- 对象化的参数会对复杂的排序提高可读性、易用性。如:RelationWrapper 对参数进行抽象
- 入口调用方法
- AggregationOperation加工方法
-
- 思路。此文编程部分思路大部分通过文心一言(免费版本即可) 获取。
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。