!!!注意细节:mongo的映射关系,还有文档名必须正确还要注意层级关系!
listThingPropertiesData(String thingId, String keyWords, Integer pageSize, Integer pageNum) {
ThingModelDTO thingModelData = getThingModelByThingId(thingId);
// 遍历设备物模型的所有属性,每个属性读取最新值
List propertiesData = new ArrayList<>();
// 创建一个空的关键字条件
Criteria keywordCriteria = new Criteria();
// 如果有关键字,添加模糊匹配规则
if (StringUtils.hasText(keyWords)) {
keywordCriteria = keywordCriteria.orOperator(
Criteria.where("property.identifier").regex(keyWords, "i"), // 匹配标识符
Criteria.where("property.value").regex(keyWords, "i") // 匹配属性值
);
}
for (ThingModelDTO.PropertyDTO propSpecDTO : propertiesSpec) {
String propIdentifier = propSpecDTO.getIdentifier();
// 第一步:构建基本查询条件,根据thingId和属性标识符查询
Criteria baseCriteria = Criteria.where("thingId").is(thingId)
.and("property.identifier").is(propIdentifier);
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.match(baseCriteria),
// 如果有关键字,再执行模糊匹配
Aggregation.match(keywordCriteria),
Aggregation.sort(Sort.by(Sort.Order.desc("property.timestamp"))),
Aggregation.group("property.identifier")
.first("property.identifier").as("identifier")
.first("property.value").as("value")
.first("property.timestamp").as("timestamp")
);
try {
AggregationResults aggregationResults = mongoTemplate.aggregate(
aggregation,"thingData", ThingData.PropertyData.class);
List matchingData = aggregationResults.getMappedResults();
propertiesData.addAll(matchingData);
// 添加ThingModel中有但ThingData中没有的属性
if (matchingData.isEmpty()) {
propertiesData.add(new ThingData.PropertyData("ThingModel:" + propSpecDTO.getIdentifier(), null, System.currentTimeMillis()));
}
}catch (Exception e) {
log.debug("查询失败! 原因" + e);
throw new ServiceException(ServiceException.ExceptionType.INTERNAL_FAILURE,
ExceptionInfoBuilder.build(ExceptionTemplate.INTERNAL_FAILURE_DATABASE,"聚合查询"));
}
}
List propertyDataDTOs = ThingDataMapper.INSTANCE.toPropertyDTO(propertiesData);
int startIndex = (pageNum - 1) * pageSize;
int endIndex = Math.min(startIndex + pageSize, propertyDataDTOs.size());
List paginatedList = propertyDataDTOs.stream()
.skip(startIndex)
.limit(endIndex - startIndex)
.collect(Collectors.toList());
return ResponseDTOBuilder.build(paginatedList, propertyDataDTOs.size(), pageSize, pageNum);
}
listThingServicesData(String thingId, String status, Long startTime, Long endTime, Integer pageSize, Integer pageNum) throws ServiceException {
// 遍历设备物模型的所有服务,每个服务读取最新值
List servicesData = new ArrayList<>();
for (ThingModelDTO.ServiceDTO serviceSpecDTO : servicesSpec) {
String serviceIdentifier = serviceSpecDTO.getIdentifier();
// 构建基本查询条件,根据thingId和服务标识符查询
Criteria baseCriteria = Criteria.where("thingId").is(thingId)
.and("service.identifier").is(serviceIdentifier);
// 创建一个空的关键字条件
Criteria keywordCriteria = new Criteria();
if (status != null && !status.isEmpty()) {
keywordCriteria = keywordCriteria.and("service.status").is(status);
}
// 如果有时间范围,添加时间范围匹配规则
if (startTime != null && endTime != null) {
keywordCriteria = keywordCriteria.and("service.timestamp").gte(startTime).lte(endTime);
} else if (startTime != null) {
keywordCriteria = keywordCriteria.and("service.timestamp").gte(startTime);
} else if (endTime != null) {
keywordCriteria = keywordCriteria.and("service.timestamp").lte(endTime);
}
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.match(baseCriteria),
Aggregation.match(keywordCriteria),
Aggregation.sort(Sort.by(Sort.Order.desc("service.timestamp"))),
Aggregation.group("service.identifier")
.first("service.identifier").as("identifier")
.first("service.status").as("status")
.first("service.serviceName").as("serviceName")
.first("service.callType").as("callType")
.first("service.inputParams").as("inputParams")
.first("service.outputParams").as("outputParams")
.first("service.timestamp").as("timestamp")
);
try{
AggregationResults aggregationResults = mongoTemplate.aggregate(
aggregation, "thingData", ThingData.ServiceData.class);
ThingData.ServiceData data = aggregationResults.getUniqueMappedResult();
servicesData.add(Objects.requireNonNullElseGet(data, () -> new ThingData.ServiceData(serviceSpecDTO.getIdentifier(), serviceSpecDTO.getServiceName(),
null, serviceSpecDTO.getCallType(), serviceSpecDTO.getInputParams(), serviceSpecDTO.getOutputParams(), System.currentTimeMillis())));
} catch (Exception e) {
log.debug("聚合查询失败! 原因" + e);
throw new ServiceException(ServiceException.ExceptionType.INTERNAL_FAILURE,
ExceptionInfoBuilder.build(ExceptionTemplate.INTERNAL_FAILURE_DATABASE,"聚合查询"));
}
}
List serviceDataDTOs = ThingDataMapper.INSTANCE.toServiceDTO(servicesData);
int startIndex = (pageNum - 1) * pageSize;
int endIndex = Math.min(startIndex + pageSize, serviceDataDTOs.size());
List paginatedList = serviceDataDTOs.stream()
.skip(startIndex)
.limit(endIndex - startIndex)
.collect(Collectors.toList());
return ResponseDTOBuilder.build(paginatedList, serviceDataDTOs.size(), pageSize, pageNum);
}
核心如下:
Query query = new Query();
Criteria criteria = new Criteria();
if (StringUtils.hasText(productId)) {
// 如果提供了 productId,将其作为查询条件
query.addCriteria(Criteria.where("product.id").is(productId));
}
if (StringUtils.hasText(nodeType)) {
//获取符合 nodeType 的所有产品的 productId 列表
Criteria nodeTypeCriteria = Criteria.where("attributes.nodeType").is(nodeType);
List products = mongoTemplate.find(Query.query(nodeTypeCriteria), Product.class);
if (!products.isEmpty()) {
List orCriteriaList = new ArrayList<>();
for (Product product : products) {
// 将ID添加到查询条件中
orCriteriaList.add(Criteria.where("product.id").is(product.getId()));
}
// 将 Criteria 列表组合成单个 $or 表达式
criteria.orOperator(orCriteriaList.toArray(new Criteria[0]));
}
}
if (StringUtils.hasText(thingStatus)) {
// 如果提供了 thingStatus,将其作为查询条件
query.addCriteria(Criteria.where("status").is(thingStatus));
}
// 如果没有提供关键字,只需执行分页查询,同时过滤掉已删除的设备
query.addCriteria(Criteria.where("deletedAt").is(null));
if (StringUtils.hasText(keyWords)) {
// 如果提供了 keyWords,添加关键字搜索条件
Pattern pattern = Pattern.compile(".*" + keyWords + ".*", Pattern.CASE_INSENSITIVE);
criteria.orOperator(
Criteria.where("name").regex(pattern),
Criteria.where("id").regex(pattern)
);
}
query.addCriteria(criteria);
// 获取符合条件的设备总数
long totalCount = mongoTemplate.count(query, Thing.class);
int skip = (pageNum - 1) * pageSize;
query.skip(skip).limit(pageSize);
try {
List things = mongoTemplate.find(query, Thing.class);
return ResponseDTOBuilder.build(ThingMapper.INSTANCE.toDTO(things), totalCount, pageSize, pageNum);
} catch (Exception e) {
log.error("查询设备失败" + e);
throw new ServiceException(
ServiceException.ExceptionType.INTERNAL_FAILURE,
ExceptionInfoBuilder.build(ExceptionTemplate.INTERNAL_FAILURE_DATABASE,"查询设备")
);
}