mongodb之使用聚合方法条件排序查询

02-29 1316阅读

目录

mongodb之使用聚合方法条件排序查询
(图片来源网络,侵删)

一、springboot使用聚合方法处理业务查询排序心得

  • 思路
  • 提的问题

    二、分页代码

    三、对二中condSortParam参数进行加工后的程序

    • AggregationOperation加工方法
    • 入口调用方法

      五、总结


      一、springboot使用聚合方法处理业务查询排序心得

      1. 思路。此文编程部分思路大部分通过文心一言(免费版本即可) 获取。

        注意:但在首次使用所给的答案绕了远路,第二回通过给他发送明确的内容做基础,如发送 mongosh脚本后 给出了编码 才拿到正确的解答方式

        注意:在springboot中使用正确的方式编程,springboot中使用aggregate方法与使用mongosh 脚本基本方法名称相同, 不然会出现问题(奇怪的问题)

      2. 如下是提的问题。询问文心一言内容
      • 注意首先编写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 对参数进行抽象
VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]