Merge branch 'improve-entity-data-query' of github.com:AndriiLandiak/thingsboard

This commit is contained in:
Andrii Shvaika 2024-04-03 17:01:32 +03:00
commit bd2cf904e4
3 changed files with 57 additions and 5 deletions

View File

@ -20,7 +20,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;

View File

@ -1109,13 +1109,14 @@ public class UserControllerTest extends AbstractControllerTest {
private List<UserEmailInfo> getUsersInfo(PageLink pageLink) throws Exception { private List<UserEmailInfo> getUsersInfo(PageLink pageLink) throws Exception {
List<UserEmailInfo> loadedCustomerUsers = new ArrayList<>(); List<UserEmailInfo> loadedCustomerUsers = new ArrayList<>();
PageData<UserEmailInfo> pageData = null; PageData<UserEmailInfo> pageData;
do { do {
pageData = doGetTypedWithPageLink("/api/users/info?", new TypeReference<>() { pageData = doGetTypedWithPageLink("/api/users/info?", new TypeReference<>() {
}, pageLink); }, pageLink);
loadedCustomerUsers.addAll(pageData.getData()); loadedCustomerUsers.addAll(pageData.getData());
if (pageData.hasNext()) { if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink(); pageLink = pageLink.nextPageLink();
Assert.assertEquals(pageLink.getPageSize(), pageData.getData().size());
} }
} while (pageData.hasNext()); } while (pageData.hasNext());
return loadedCustomerUsers; return loadedCustomerUsers;

View File

@ -20,6 +20,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.HasCustomerId; import org.thingsboard.server.common.data.HasCustomerId;
import org.thingsboard.server.common.data.HasEmail; import org.thingsboard.server.common.data.HasEmail;
import org.thingsboard.server.common.data.HasLabel; import org.thingsboard.server.common.data.HasLabel;
@ -34,13 +35,18 @@ import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.query.EntityCountQuery; import org.thingsboard.server.common.data.query.EntityCountQuery;
import org.thingsboard.server.common.data.query.EntityData; import org.thingsboard.server.common.data.query.EntityData;
import org.thingsboard.server.common.data.query.EntityDataPageLink;
import org.thingsboard.server.common.data.query.EntityDataQuery; import org.thingsboard.server.common.data.query.EntityDataQuery;
import org.thingsboard.server.common.data.query.EntityFilterType; import org.thingsboard.server.common.data.query.EntityFilterType;
import org.thingsboard.server.common.data.query.EntityKey;
import org.thingsboard.server.common.data.query.EntityListFilter;
import org.thingsboard.server.common.data.query.RelationsQueryFilter; import org.thingsboard.server.common.data.query.RelationsQueryFilter;
import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.exception.IncorrectParameterException;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors;
import static org.thingsboard.server.common.data.id.EntityId.NULL_UUID; import static org.thingsboard.server.common.data.id.EntityId.NULL_UUID;
import static org.thingsboard.server.dao.service.Validator.validateEntityDataPageLink; import static org.thingsboard.server.dao.service.Validator.validateEntityDataPageLink;
@ -79,9 +85,55 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe
validateId(tenantId, INCORRECT_TENANT_ID + tenantId); validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
validateId(customerId, INCORRECT_CUSTOMER_ID + customerId); validateId(customerId, INCORRECT_CUSTOMER_ID + customerId);
validateEntityDataQuery(query); validateEntityDataQuery(query);
if (EntityFilterType.RELATIONS_QUERY.equals(query.getEntityFilter().getType())
|| EntityFilterType.SINGLE_ENTITY.equals(query.getEntityFilter().getType())
|| StringUtils.isNotEmpty(query.getPageLink().getTextSearch())) {
return this.entityQueryDao.findEntityDataByQuery(tenantId, customerId, query); return this.entityQueryDao.findEntityDataByQuery(tenantId, customerId, query);
} }
// 1 step - find entity data by filter and sort columns
PageData<EntityData> entityDataByQuery = findEntityIdsByFilterAndSorterColumns(tenantId, customerId, query);
if (entityDataByQuery == null || entityDataByQuery.getData().isEmpty()) {
return entityDataByQuery;
}
// 2 step - find entity data by entity ids from the 1st step
PageData<EntityData> result = findEntityDataByEntityIds(tenantId, customerId, query, entityDataByQuery.getData());
return new PageData<>(result.getData(), entityDataByQuery.getTotalPages(), entityDataByQuery.getTotalElements(), entityDataByQuery.hasNext());
}
private PageData<EntityData> findEntityIdsByFilterAndSorterColumns(TenantId tenantId, CustomerId customerId, EntityDataQuery query) {
List<EntityKey> entityFields = null;
List<EntityKey> latestValues = null;
if (query.getPageLink().getSortOrder() != null) {
if (query.getEntityFields() != null) {
entityFields = query.getEntityFields().stream()
.filter(entityKey -> entityKey.getKey().equals(query.getPageLink().getSortOrder().getKey().getKey()))
.collect(Collectors.toList());
}
if (query.getLatestValues() != null) {
latestValues = query.getLatestValues().stream()
.filter(entityKey -> entityKey.getKey().equals(query.getPageLink().getSortOrder().getKey().getKey()))
.collect(Collectors.toList());
}
}
EntityDataQuery entityQuery = new EntityDataQuery(query.getEntityFilter(), query.getPageLink(), entityFields, latestValues, query.getKeyFilters());
return this.entityQueryDao.findEntityDataByQuery(tenantId, customerId, entityQuery);
}
private PageData<EntityData> findEntityDataByEntityIds(TenantId tenantId, CustomerId customerId, EntityDataQuery query, List<EntityData> data) {
List<String> entityIds = data.stream().map(d -> d.getEntityId().getId().toString()).toList();
EntityType entityType = data.isEmpty() ? null : data.get(0).getEntityId().getEntityType();
EntityListFilter filter = new EntityListFilter();
filter.setEntityType(entityType);
filter.setEntityList(entityIds);
EntityDataPageLink pageLink = new EntityDataPageLink(query.getPageLink().getPageSize(), 0, null, query.getPageLink().getSortOrder());
EntityDataQuery entityQuery = new EntityDataQuery(filter, pageLink, query.getEntityFields(), query.getLatestValues(), null);
return this.entityQueryDao.findEntityDataByQuery(tenantId, customerId, entityQuery);
}
@Override @Override
public Optional<String> fetchEntityName(TenantId tenantId, EntityId entityId) { public Optional<String> fetchEntityName(TenantId tenantId, EntityId entityId) {
log.trace("Executing fetchEntityName [{}]", entityId); log.trace("Executing fetchEntityName [{}]", entityId);
@ -133,8 +185,7 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe
} }
private CustomerId getCustomerId(HasId<?> entity) { private CustomerId getCustomerId(HasId<?> entity) {
if (entity instanceof HasCustomerId) { if (entity instanceof HasCustomerId hasCustomerId) {
HasCustomerId hasCustomerId = (HasCustomerId) entity;
CustomerId customerId = hasCustomerId.getCustomerId(); CustomerId customerId = hasCustomerId.getCustomerId();
if (customerId == null) { if (customerId == null) {
customerId = NULL_CUSTOMER_ID; customerId = NULL_CUSTOMER_ID;
@ -176,4 +227,5 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe
throw new IncorrectParameterException("Relation query filter root entity should not be blank"); throw new IncorrectParameterException("Relation query filter root entity should not be blank");
} }
} }
} }