diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationsSearchParameters.java b/common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationsSearchParameters.java index 840eb2a529..9963d3e75b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationsSearchParameters.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationsSearchParameters.java @@ -35,17 +35,19 @@ public class RelationsSearchParameters { private EntitySearchDirection direction; private RelationTypeGroup relationTypeGroup; private int maxLevel = 1; + private boolean fetchLastLevelOnly; - public RelationsSearchParameters(EntityId entityId, EntitySearchDirection direction, int maxLevel) { - this(entityId, direction, maxLevel, RelationTypeGroup.COMMON); + public RelationsSearchParameters(EntityId entityId, EntitySearchDirection direction, int maxLevel, boolean fetchLastLevelOnly) { + this(entityId, direction, maxLevel, RelationTypeGroup.COMMON, fetchLastLevelOnly); } - public RelationsSearchParameters(EntityId entityId, EntitySearchDirection direction, int maxLevel, RelationTypeGroup relationTypeGroup) { + public RelationsSearchParameters(EntityId entityId, EntitySearchDirection direction, int maxLevel, RelationTypeGroup relationTypeGroup, boolean fetchLastLevelOnly) { this.rootId = entityId.getId(); this.rootType = entityId.getEntityType(); this.direction = direction; this.maxLevel = maxLevel; this.relationTypeGroup = relationTypeGroup; + this.fetchLastLevelOnly = fetchLastLevelOnly; } public EntityId getEntityId() { diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java index 3d81dafb5c..d83b068cbe 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java @@ -153,7 +153,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ private List getParentEntities(Alarm alarm) throws InterruptedException, ExecutionException { EntityRelationsQuery query = new EntityRelationsQuery(); - query.setParameters(new RelationsSearchParameters(alarm.getOriginator(), EntitySearchDirection.TO, Integer.MAX_VALUE)); + query.setParameters(new RelationsSearchParameters(alarm.getOriginator(), EntitySearchDirection.TO, Integer.MAX_VALUE, false)); return relationService.findByQuery(alarm.getTenantId(), query).get().stream().map(EntityRelation::getFrom).collect(Collectors.toList()); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java b/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java index 164d3036e1..75739c7048 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java @@ -26,7 +26,6 @@ import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Caching; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; -import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.relation.EntityRelation; @@ -443,6 +442,7 @@ public class BaseRelationService implements RelationService { @Override public ListenableFuture> findByQuery(TenantId tenantId, EntityRelationsQuery query) { + //boolean fetchLastLevelOnly = true; log.trace("Executing findByQuery [{}]", query); RelationsSearchParameters params = query.getParameters(); final List filters = query.getFilters(); @@ -453,7 +453,7 @@ public class BaseRelationService implements RelationService { int maxLvl = params.getMaxLevel() > 0 ? params.getMaxLevel() : Integer.MAX_VALUE; try { - ListenableFuture> relationSet = findRelationsRecursively(tenantId, params.getEntityId(), params.getDirection(), params.getRelationTypeGroup(), maxLvl, new ConcurrentHashMap<>()); + ListenableFuture> relationSet = findRelationsRecursively(tenantId, params.getEntityId(), params.getDirection(), params.getRelationTypeGroup(), maxLvl, params.isFetchLastLevelOnly(), new ConcurrentHashMap<>()); return Futures.transform(relationSet, input -> { List relations = new ArrayList<>(); if (filters == null || filters.isEmpty()) { @@ -570,7 +570,7 @@ public class BaseRelationService implements RelationService { } private ListenableFuture> findRelationsRecursively(final TenantId tenantId, final EntityId rootId, final EntitySearchDirection direction, - RelationTypeGroup relationTypeGroup, int lvl, + RelationTypeGroup relationTypeGroup, int lvl, boolean fetchLastLevelOnly, final ConcurrentHashMap uniqueMap) throws Exception { if (lvl == 0) { return Futures.immediateFuture(Collections.emptySet()); @@ -596,10 +596,13 @@ public class BaseRelationService implements RelationService { } List>> futures = new ArrayList<>(); for (EntityId entityId : childrenIds) { - futures.add(findRelationsRecursively(tenantId, entityId, direction, relationTypeGroup, lvl, uniqueMap)); + futures.add(findRelationsRecursively(tenantId, entityId, direction, relationTypeGroup, lvl, fetchLastLevelOnly, uniqueMap)); } //TODO: try to remove this blocking operation List> relations = Futures.successfulAsList(futures).get(); + if (fetchLastLevelOnly && lvl > 0){ + children.clear(); + } relations.forEach(r -> r.forEach(children::add)); return Futures.immediateFuture(children); } diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseRelationServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseRelationServiceTest.java index 7e29101214..f6e6daded2 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseRelationServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseRelationServiceTest.java @@ -220,7 +220,7 @@ public abstract class BaseRelationServiceTest extends AbstractServiceTest { saveRelation(relationC); EntityRelationsQuery query = new EntityRelationsQuery(); - query.setParameters(new RelationsSearchParameters(assetA, EntitySearchDirection.FROM, -1)); + query.setParameters(new RelationsSearchParameters(assetA, EntitySearchDirection.FROM, -1, false)); query.setFilters(Collections.singletonList(new EntityTypeFilter(EntityRelation.CONTAINS_TYPE, Collections.singletonList(EntityType.ASSET)))); List relations = relationService.findByQuery(SYSTEM_TENANT_ID, query).get(); Assert.assertEquals(3, relations.size()); @@ -254,7 +254,7 @@ public abstract class BaseRelationServiceTest extends AbstractServiceTest { saveRelation(relationBD); EntityRelationsQuery query = new EntityRelationsQuery(); - query.setParameters(new RelationsSearchParameters(assetA, EntitySearchDirection.FROM, -1)); + query.setParameters(new RelationsSearchParameters(assetA, EntitySearchDirection.FROM, -1, false)); query.setFilters(Collections.singletonList(new EntityTypeFilter(EntityRelation.CONTAINS_TYPE, Collections.singletonList(EntityType.ASSET)))); List relations = relationService.findByQuery(SYSTEM_TENANT_ID, query).get(); Assert.assertEquals(2, relations.size()); diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/data/DeviceRelationsQuery.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/data/DeviceRelationsQuery.java index 2a5ce73576..95a075ff67 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/data/DeviceRelationsQuery.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/data/DeviceRelationsQuery.java @@ -26,4 +26,5 @@ public class DeviceRelationsQuery { private int maxLevel = 1; private String relationType; private List deviceTypes; + private boolean fetchLastLevelOnly; } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/data/RelationsQuery.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/data/RelationsQuery.java index 05375313f9..2cafd7b2bf 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/data/RelationsQuery.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/data/RelationsQuery.java @@ -27,5 +27,5 @@ public class RelationsQuery { private EntitySearchDirection direction; private int maxLevel = 1; private List filters; - + private boolean fetchLastLevelOnly = false; } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesRelatedDeviceIdAsyncLoader.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesRelatedDeviceIdAsyncLoader.java index c4bad61bd2..52ea90fde9 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesRelatedDeviceIdAsyncLoader.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesRelatedDeviceIdAsyncLoader.java @@ -46,7 +46,7 @@ public class EntitiesRelatedDeviceIdAsyncLoader { private static DeviceSearchQuery buildQuery(EntityId originator, DeviceRelationsQuery deviceRelationsQuery) { DeviceSearchQuery query = new DeviceSearchQuery(); RelationsSearchParameters parameters = new RelationsSearchParameters(originator, - deviceRelationsQuery.getDirection(), deviceRelationsQuery.getMaxLevel()); + deviceRelationsQuery.getDirection(), deviceRelationsQuery.getMaxLevel(), deviceRelationsQuery.isFetchLastLevelOnly()); query.setParameters(parameters); query.setRelationType(deviceRelationsQuery.getRelationType()); query.setDeviceTypes(deviceRelationsQuery.getDeviceTypes()); diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesRelatedEntityIdAsyncLoader.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesRelatedEntityIdAsyncLoader.java index aae9d4ea22..158ba4f1a7 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesRelatedEntityIdAsyncLoader.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesRelatedEntityIdAsyncLoader.java @@ -50,7 +50,7 @@ public class EntitiesRelatedEntityIdAsyncLoader { private static EntityRelationsQuery buildQuery(EntityId originator, RelationsQuery relationsQuery) { EntityRelationsQuery query = new EntityRelationsQuery(); RelationsSearchParameters parameters = new RelationsSearchParameters(originator, - relationsQuery.getDirection(), relationsQuery.getMaxLevel()); + relationsQuery.getDirection(), relationsQuery.getMaxLevel(), relationsQuery.isFetchLastLevelOnly()); query.setParameters(parameters); query.setFilters(relationsQuery.getFilters()); return query;