| | |
| | | */ |
| | | @Override |
| | | public Result videoOneMachineDocumentQualified(DataCenterQuery params) { |
| | | long startTime = System.currentTimeMillis(); |
| | | List<String> likeFileds = Arrays.asList("ip.showValue", "name.showValue", "serialNumber.showValue"); |
| | | SysDept sysDept = getSysDeptByLoginUser(); |
| | | List<Criteria> andCriteria; |
| | |
| | | long total = mongoTemplate.count(query, MonitorQualifyResult.class); |
| | | MongoUtil.setPage(query, params, TIME_FIELD); |
| | | List<MonitorQualifyResult> resultList = mongoTemplate.find(query, MonitorQualifyResult.class); |
| | | |
| | | List<MonitorQualifyResultVO> resultVOS = new ArrayList<>(); |
| | | for (MonitorQualifyResult result : resultList) { |
| | | MonitorQualifyResultVO vo = MonitorQualifyResult.getVO(result); |
| | | resultVOS.add(vo); |
| | | } |
| | | // 统计数量 |
| | | long endTime = System.currentTimeMillis(); |
| | | // 统计数量(改造后:一次聚合返回所有结果) |
| | | long startTime2 = System.currentTimeMillis(); |
| | | MongoDatabase database = mongoTemplate.getDb(); |
| | | MongoCollection<Document> collection = database.getCollection("uy_monitor_qualify"); |
| | | Document areDocument = null; |
| | | |
| | | // 1. 构建公共过滤条件(deviceNo前缀 + tag过滤) |
| | | List<Document> commonFilters = new ArrayList<>(2); |
| | | if (areaDeptEnum != null) { |
| | | String areaCodePrefix = areaDeptEnum.getCode(); |
| | | areDocument = new Document("deviceNo", new Document("$regex", "^" + areaCodePrefix)); |
| | | commonFilters.add(new Document("deviceNo", new Document("$regex", "^" + areaCodePrefix))); |
| | | } |
| | | //总数 |
| | | List<Document> dList1 = new ArrayList<>(2); |
| | | if (areDocument != null){ |
| | | dList1.add(areDocument); |
| | | } |
| | | setTag(params, dList1); |
| | | Document totalFilter = new Document("$and", dList1); |
| | | //list1 |
| | | setTag(params, commonFilters); // 添加tag过滤条件 |
| | | Document commonFilter = commonFilters.isEmpty() ? new Document() : new Document("$and", commonFilters); |
| | | |
| | | //合格数 |
| | | List<Document> dList2 = new ArrayList<>(2); |
| | | if (areDocument != null){ |
| | | dList2.add(areDocument); |
| | | } |
| | | dList2.add(new Document("serialNumber.error", Boolean.FALSE)); |
| | | dList2.add(new Document("name.error", Boolean.FALSE)); |
| | | dList2.add(new Document("civilCode.error", Boolean.FALSE)); |
| | | dList2.add(new Document("integrated_device.error", Boolean.FALSE)); |
| | | dList2.add(new Document("jkdwlx.error", Boolean.FALSE)); |
| | | dList2.add(new Document("latitude.error", Boolean.FALSE)); |
| | | dList2.add(new Document("longitude.error", Boolean.FALSE)); |
| | | dList2.add(new Document("macdz.error", Boolean.FALSE)); |
| | | dList2.add(new Document("name.error", Boolean.FALSE)); |
| | | dList2.add(new Document("sbzt.error", Boolean.FALSE)); |
| | | dList2.add(new Document("sxjcjqy.error", Boolean.FALSE)); |
| | | dList2.add(new Document("sxjgnlx.error", Boolean.FALSE)); |
| | | setTag(params, dList2); |
| | | Document qualifyFilter = new Document("$and", dList2); |
| | | //不合格数 |
| | | List<Document> dList3 = new ArrayList<>(2); |
| | | if (areDocument != null){ |
| | | dList3.add(areDocument); |
| | | } |
| | | setTag(params, dList3); |
| | | List<Document> errorConditions = new ArrayList<>(); |
| | | errorConditions.add(new Document("serialNumber.error", new Document("$eq", Boolean.TRUE))); |
| | | errorConditions.add(new Document("name.error", new Document("$eq", Boolean.TRUE))); |
| | | errorConditions.add(new Document("civilCode.error", new Document("$eq", Boolean.TRUE))); |
| | | errorConditions.add(new Document("integrated_device.error", new Document("$eq", Boolean.TRUE))); |
| | | errorConditions.add(new Document("jkdwlx.error", new Document("$eq", Boolean.TRUE))); |
| | | errorConditions.add(new Document("latitude.error", new Document("$eq", Boolean.TRUE))); |
| | | errorConditions.add(new Document("longitude.error", new Document("$eq", Boolean.TRUE))); |
| | | errorConditions.add(new Document("macdz.error", new Document("$eq", Boolean.TRUE))); |
| | | errorConditions.add(new Document("name.error", new Document("$eq", Boolean.TRUE))); |
| | | errorConditions.add(new Document("sbzt.error", new Document("$eq", Boolean.TRUE))); |
| | | errorConditions.add(new Document("sxjcjqy.error", new Document("$eq", Boolean.TRUE))); |
| | | errorConditions.add(new Document("sxjgnlx.error", new Document("$eq", Boolean.TRUE))); |
| | | Document errorFilter = new Document("$or", errorConditions); |
| | | dList3.add(errorFilter); |
| | | Document unQualifyFilter = new Document("$and", dList3); |
| | | // 2. 构建合格/不合格的error条件(复用原逻辑,去重name.error) |
| | | // 合格条件:所有error为false |
| | | List<Document> qualifyErrorConditions = new ArrayList<>(); |
| | | qualifyErrorConditions.add(new Document("serialNumber.error", Boolean.FALSE)); |
| | | qualifyErrorConditions.add(new Document("name.error", Boolean.FALSE)); |
| | | qualifyErrorConditions.add(new Document("civilCode.error", Boolean.FALSE)); |
| | | qualifyErrorConditions.add(new Document("integrated_device.error", Boolean.FALSE)); |
| | | qualifyErrorConditions.add(new Document("jkdwlx.error", Boolean.FALSE)); |
| | | qualifyErrorConditions.add(new Document("latitude.error", Boolean.FALSE)); |
| | | qualifyErrorConditions.add(new Document("longitude.error", Boolean.FALSE)); |
| | | qualifyErrorConditions.add(new Document("macdz.error", Boolean.FALSE)); |
| | | qualifyErrorConditions.add(new Document("sbzt.error", Boolean.FALSE)); |
| | | qualifyErrorConditions.add(new Document("sxjcjqy.error", Boolean.FALSE)); |
| | | qualifyErrorConditions.add(new Document("sxjgnlx.error", Boolean.FALSE)); |
| | | Document qualifyFilter = new Document("$and", qualifyErrorConditions); |
| | | |
| | | List<Document> lists = Arrays.asList(totalFilter, qualifyFilter, unQualifyFilter); |
| | | List<String> rList = lists.stream().map(filter -> { |
| | | // 构建聚合管道 |
| | | List<Document> pipeline = Arrays.asList( |
| | | new Document("$match", filter), |
| | | // $group 去重 |
| | | new Document("$group", new Document("_id", "$serialNumber.showValue")), |
| | | new Document("$count", "uniqueDeviceIds") |
| | | ); |
| | | // 执行聚合查询并获取结果 |
| | | AggregateIterable<Document> result = collection.aggregate(pipeline); |
| | | Integer uniqueDeviceIdCount = 0; |
| | | for (Document doc : result) { |
| | | uniqueDeviceIdCount = doc.getInteger("uniqueDeviceIds"); |
| | | break; // 不需要继续遍历,因为 $count 只会产生一个结果 |
| | | } |
| | | return uniqueDeviceIdCount + ""; |
| | | }).collect(Collectors.toList()); |
| | | // 不合格条件:至少一个error为true |
| | | List<Document> unQualifyErrorConditions = new ArrayList<>(); |
| | | unQualifyErrorConditions.add(new Document("serialNumber.error", Boolean.TRUE)); |
| | | unQualifyErrorConditions.add(new Document("name.error", Boolean.TRUE)); |
| | | unQualifyErrorConditions.add(new Document("civilCode.error", Boolean.TRUE)); |
| | | unQualifyErrorConditions.add(new Document("integrated_device.error", Boolean.TRUE)); |
| | | unQualifyErrorConditions.add(new Document("jkdwlx.error", Boolean.TRUE)); |
| | | unQualifyErrorConditions.add(new Document("latitude.error", Boolean.TRUE)); |
| | | unQualifyErrorConditions.add(new Document("longitude.error", Boolean.TRUE)); |
| | | unQualifyErrorConditions.add(new Document("macdz.error", Boolean.TRUE)); |
| | | unQualifyErrorConditions.add(new Document("sbzt.error", Boolean.TRUE)); |
| | | unQualifyErrorConditions.add(new Document("sxjcjqy.error", Boolean.TRUE)); |
| | | unQualifyErrorConditions.add(new Document("sxjgnlx.error", Boolean.TRUE)); |
| | | Document unQualifyFilter = new Document("$or", unQualifyErrorConditions); |
| | | |
| | | // 3. 构建一次聚合管道(用$facet合并三个统计维度) |
| | | List<Document> pipeline = new ArrayList<>(); |
| | | |
| | | // 步骤1:先应用公共过滤条件(deviceNo + tag),减少后续处理数据量 |
| | | if (!commonFilters.isEmpty()) { |
| | | pipeline.add(new Document("$match", commonFilter)); |
| | | } |
| | | |
| | | // 步骤2:用$facet分面查询,同时计算总数、合格数、不合格数 |
| | | pipeline.add(new Document("$facet", new Document() |
| | | // 总数:按serialNumber.showValue去重后计数 |
| | | .append("total", Arrays.asList( |
| | | new Document("$group", new Document("_id", "$serialNumber.showValue")), |
| | | new Document("$count", "uniqueDeviceIds") |
| | | )) |
| | | // 合格数:先过滤合格条件,再去重计数 |
| | | .append("qualify", Arrays.asList( |
| | | new Document("$match", qualifyFilter), |
| | | new Document("$group", new Document("_id", "$serialNumber.showValue")), |
| | | new Document("$count", "uniqueDeviceIds") |
| | | )) |
| | | // 不合格数:先过滤不合格条件,再去重计数 |
| | | .append("unQualify", Arrays.asList( |
| | | new Document("$match", unQualifyFilter), |
| | | new Document("$group", new Document("_id", "$serialNumber.showValue")), |
| | | new Document("$count", "uniqueDeviceIds") |
| | | )) |
| | | )); |
| | | // Document explainResult = collection.aggregate(pipeline).explain(); |
| | | // |
| | | //// 打印执行计划(日志或控制台输出) |
| | | // log.info("聚合查询执行计划:{}", explainResult.toJson()); |
| | | // 4. 执行聚合查询(仅一次数据库交互) |
| | | AggregateIterable<Document> facetResult = collection.aggregate(pipeline).allowDiskUse(true); |
| | | Document resultDoc = facetResult.iterator().next(); // $facet仅返回一个文档 |
| | | |
| | | // 5. 解析结果(处理空结果场景,默认计数为0) |
| | | int totalCount = parseFacetCount(resultDoc, "total"); |
| | | int qualifyCount = parseFacetCount(resultDoc, "qualify"); |
| | | int unQualifyCount = parseFacetCount(resultDoc, "unQualify"); |
| | | |
| | | // 6. 组装rList(保持原格式不变,后续逻辑无需修改) |
| | | List<String> rList = new ArrayList<>(Arrays.asList( |
| | | String.valueOf(totalCount), |
| | | String.valueOf(qualifyCount), |
| | | String.valueOf(unQualifyCount) |
| | | )); |
| | | // 原合格率计算逻辑不变 |
| | | BigDecimal onlineRate = BigDecimal.ZERO; |
| | | if (!StringUtils.isEmpty(rList.get(0)) && !"0".equals(rList.get(0))) { |
| | | onlineRate = new BigDecimal(rList.get(1)).divide(new BigDecimal(rList.get(0)), 3,RoundingMode.DOWN).multiply(new BigDecimal("100")); |
| | | if (totalCount != 0) { |
| | | onlineRate = new BigDecimal(qualifyCount) |
| | | .divide(new BigDecimal(totalCount), 3, RoundingMode.DOWN) |
| | | .multiply(new BigDecimal("100")); |
| | | } |
| | | rList.add(this.remove0(onlineRate)); |
| | | |
| | | long endTime2 = System.currentTimeMillis(); |
| | | log.info("统计耗时:{} ms", (endTime2 - startTime2)); |
| | | |
| | | rList.add(this.remove0(onlineRate)); |
| | | HashMap<String, Object> map = new HashMap<>(); |
| | | map.put("count", rList); |
| | | map.put("list", resultVOS); |
| | | return Result.ok().data(map).total(total); |
| | | } |
| | | |
| | | private int parseFacetCount(Document resultDoc, String facetName) { |
| | | List<Document> facetList = (List<Document>) resultDoc.get(facetName); |
| | | if (facetList == null || facetList.isEmpty()) { |
| | | return 0; |
| | | } |
| | | Document countDoc = facetList.get(0); |
| | | return countDoc.getInteger("uniqueDeviceIds", 0); |
| | | } |
| | | /** |
| | | * 视频:档案考核比 |
| | | * 档案留存总量:mongo存的所有去重后的档案 |