From a8a498929bb4cecce5298a06a5a6894fe3763b95 Mon Sep 17 00:00:00 2001 From: Serafeim Chatzopoulos Date: Fri, 14 Jun 2024 09:49:00 +0300 Subject: [PATCH] Adjust sorting clauses for all entities --- .../api/dto/request/ProjectRequest.java | 4 +-- .../dto/request/ResearchProductsRequest.java | 4 +-- .../java/eu/openaire/api/mappers/Utils.java | 28 +++++++++++++++++-- .../query/DataSourceRequestMapper.java | 6 +++- .../query/OrganizationRequestMapper.java | 6 +++- .../mappers/query/ProjectRequestMapper.java | 9 ++++-- .../query/ResearchProductsRequestMapper.java | 14 +++++++++- .../api/repositories/SolrRepository.java | 12 ++------ .../eu/openaire/api/solr/SolrQueryParams.java | 3 +- 9 files changed, 63 insertions(+), 23 deletions(-) diff --git a/src/main/java/eu/openaire/api/dto/request/ProjectRequest.java b/src/main/java/eu/openaire/api/dto/request/ProjectRequest.java index 50096e6..40ac283 100644 --- a/src/main/java/eu/openaire/api/dto/request/ProjectRequest.java +++ b/src/main/java/eu/openaire/api/dto/request/ProjectRequest.java @@ -84,7 +84,7 @@ public class ProjectRequest { @Parameter(description = "Number of results per page", schema = @Schema(defaultValue = "10", type = "integer")) private int pageSize = 10; - @Parameter(description = "The field to sort the results by and the sort direction. The format should be in the format `fieldname ASC|DESC`, where fieldname is one of 'relevance', 'projectstartyear', 'projectendyear'. Multiple sorting parameters should be comma-separated." , schema = @Schema(defaultValue = "relevance DESC")) - @Pattern(regexp = "^((relevance|projectstartyear|projectendyear)\\s+(ASC|DESC),?\\s*)+$", message = "The field should be in the format 'fieldname ASC|DESC', where fieldname is one of 'score', 'projectstartyear', 'projectendyear'. Multiple sorting parameters should be comma-separated.") + @Parameter(description = "The field to sort the results by and the sort direction. The format should be in the format `fieldname ASC|DESC`, where fieldname is one of 'relevance', 'startDate', 'endDate'. Multiple sorting parameters should be comma-separated." , schema = @Schema(defaultValue = "relevance DESC")) + @Pattern(regexp = "^((relevance|startDate|endDate)\\s+(ASC|DESC),?\\s*)+$", message = "The field should be in the format 'fieldname ASC|DESC', where fieldname is one of 'relevance', 'startDate', 'endDate'. Multiple sorting parameters should be comma-separated.") private String sortBy; } \ No newline at end of file diff --git a/src/main/java/eu/openaire/api/dto/request/ResearchProductsRequest.java b/src/main/java/eu/openaire/api/dto/request/ResearchProductsRequest.java index c0f9399..71bb411 100644 --- a/src/main/java/eu/openaire/api/dto/request/ResearchProductsRequest.java +++ b/src/main/java/eu/openaire/api/dto/request/ResearchProductsRequest.java @@ -145,7 +145,7 @@ public class ResearchProductsRequest { @Parameter(description = "Number of results per page", schema = @Schema(defaultValue = "10", type = "integer")) private int pageSize = 10; - @Parameter(description = "The field to sort the results by and the sort direction. The format should be in the format `fieldname ASC|DESC`, where fieldname is one of 'score', 'dateofcollection', 'influence', 'popularity', 'citation_count', 'impulse'. Multiple sorting parameters should be comma-separated." , schema = @Schema(defaultValue = "score DESC")) - @Pattern(regexp = "^((score|dateofcollection|influence|popularity|citation_count|impulse)\\s+(ASC|DESC),?\\s*)+$", message = "The field should be in the format 'fieldname ASC|DESC', research products can be only sorted by the 'score', 'dateofcollection', 'influence', 'citation_count', 'impulse'.") + @Parameter(description = "The field to sort the results by and the sort direction. The format should be in the format `fieldname ASC|DESC`, where fieldname is one of 'relevance', 'publicationDate', 'dateOfCollection', 'influence', 'popularity', 'citationCount', 'impulse'. Multiple sorting parameters should be comma-separated." , schema = @Schema(defaultValue = "relevance DESC")) + @Pattern(regexp = "^((relevance|publicationDate|dateOfCollection|influence|popularity|citationCount|impulse)\\s+(ASC|DESC),?\\s*)+$", message = "The field should be in the format 'fieldname ASC|DESC', research products can be only sorted by the 'relevance', 'publicationDate', 'dateOfCollection', 'influence', 'citationCount', 'impulse'.") private String sortBy; } \ No newline at end of file diff --git a/src/main/java/eu/openaire/api/mappers/Utils.java b/src/main/java/eu/openaire/api/mappers/Utils.java index 472c93a..aaa6c2b 100644 --- a/src/main/java/eu/openaire/api/mappers/Utils.java +++ b/src/main/java/eu/openaire/api/mappers/Utils.java @@ -1,6 +1,7 @@ package eu.openaire.api.mappers; import eu.openaire.api.errors.exceptions.BadRequestException; +import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.util.ClientUtils; import java.time.LocalDate; @@ -8,9 +9,7 @@ import java.time.LocalDateTime; import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; public class Utils { @@ -150,4 +149,27 @@ public class Utils { } return null; } + + static public List formatSortByParam(String sortBy, Map fieldMapping) { + + if (Utils.isNullOrEmpty(sortBy)) { + return null; + } + + List sortClauses = new ArrayList<>(); + + String[] sortByPairs = sortBy.split(","); + for (String pair : sortByPairs) { + String[] parts = pair.trim().split("\\s+"); + String field = parts[0]; + SolrQuery.ORDER order = parts[1].equalsIgnoreCase("ASC") ? SolrQuery.ORDER.asc : SolrQuery.ORDER.desc; + + String fieldName = Optional.ofNullable(fieldMapping.get(field)) + .orElseThrow(() -> new BadRequestException("Invalid field name in sortBy parameter: " + field)); + + sortClauses.add(new SolrQuery.SortClause(fieldName, order)); + } + + return sortClauses; + } } diff --git a/src/main/java/eu/openaire/api/mappers/query/DataSourceRequestMapper.java b/src/main/java/eu/openaire/api/mappers/query/DataSourceRequestMapper.java index c4d013c..b6b6f3f 100644 --- a/src/main/java/eu/openaire/api/mappers/query/DataSourceRequestMapper.java +++ b/src/main/java/eu/openaire/api/mappers/query/DataSourceRequestMapper.java @@ -11,9 +11,13 @@ import java.util.Map; @Mapper(componentModel = "spring") public interface DataSourceRequestMapper { + Map sortFieldMapping = Map.ofEntries( + Map.entry("relevance", "score") + ); + @Mapping(target = "start", expression = "java( calculateStart(src.getPage(), src.getPageSize()) )") @Mapping(target = "rows", source = "pageSize") - @Mapping(target = "sort", source = "sortBy") + @Mapping(target = "sort", expression = "java( eu.openaire.api.mappers.Utils.formatSortByParam(src.getSortBy(), sortFieldMapping) )") SolrQueryParams toSolrQuery(DataSourceRequest src); @Named("calculateStart") diff --git a/src/main/java/eu/openaire/api/mappers/query/OrganizationRequestMapper.java b/src/main/java/eu/openaire/api/mappers/query/OrganizationRequestMapper.java index 8a96273..709b9f3 100644 --- a/src/main/java/eu/openaire/api/mappers/query/OrganizationRequestMapper.java +++ b/src/main/java/eu/openaire/api/mappers/query/OrganizationRequestMapper.java @@ -11,9 +11,13 @@ import java.util.Map; @Mapper(componentModel = "spring") public interface OrganizationRequestMapper { + Map sortFieldMapping = Map.ofEntries( + Map.entry("relevance", "score") + ); + @Mapping(target = "start", expression = "java( calculateStart(src.getPage(), src.getPageSize()) )") @Mapping(target = "rows", source = "pageSize") - @Mapping(target = "sort", source = "sortBy") + @Mapping(target = "sort", expression = "java( eu.openaire.api.mappers.Utils.formatSortByParam(src.getSortBy(), sortFieldMapping) )") SolrQueryParams toSolrQuery(OrganizationRequest src); @Named("calculateStart") diff --git a/src/main/java/eu/openaire/api/mappers/query/ProjectRequestMapper.java b/src/main/java/eu/openaire/api/mappers/query/ProjectRequestMapper.java index 0ec3069..beec2c0 100644 --- a/src/main/java/eu/openaire/api/mappers/query/ProjectRequestMapper.java +++ b/src/main/java/eu/openaire/api/mappers/query/ProjectRequestMapper.java @@ -12,9 +12,15 @@ import java.util.Optional; @Mapper(componentModel = "spring") public interface ProjectRequestMapper { + Map sortFieldMapping = Map.ofEntries( + Map.entry("relevance", "score"), + Map.entry("startDate", "projectstartyear"), + Map.entry("endDate", "projectendyear") + ); + @Mapping(target = "start", expression = "java( calculateStart(src.getPage(), src.getPageSize()) )") @Mapping(target = "rows", source = "pageSize") - @Mapping(target = "sort", source = "sortBy") + @Mapping(target = "sort", expression = "java( eu.openaire.api.mappers.Utils.formatSortByParam(src.getSortBy(), sortFieldMapping) )") SolrQueryParams toSolrQuery(ProjectRequest src); @Named("calculateStart") @@ -144,7 +150,6 @@ public interface ProjectRequestMapper { solrQueryParams.setFq(fqList); - System.out.println(solrQueryParams.toString()); } } diff --git a/src/main/java/eu/openaire/api/mappers/query/ResearchProductsRequestMapper.java b/src/main/java/eu/openaire/api/mappers/query/ResearchProductsRequestMapper.java index 24d279c..e516e50 100644 --- a/src/main/java/eu/openaire/api/mappers/query/ResearchProductsRequestMapper.java +++ b/src/main/java/eu/openaire/api/mappers/query/ResearchProductsRequestMapper.java @@ -13,9 +13,21 @@ import java.util.Optional; @Mapper(componentModel = "spring") public interface ResearchProductsRequestMapper { + Map sortFieldMapping = Map.ofEntries( + + Map.entry("relevance", "score"), + Map.entry("publicationDate", "resultdateofacceptance"), + Map.entry("dateOfCollection", "dateofcollection"), + + Map.entry("influence", "influence"), + Map.entry("popularity", "popularity"), + Map.entry("citationCount", "citation_count"), + Map.entry("impulse", "impulse") + ); + @Mapping(target = "start", expression = "java( calculateStart(src.getPage(), src.getPageSize()) )") @Mapping(target = "rows", source = "pageSize") - @Mapping(target = "sort", source = "sortBy") + @Mapping(target = "sort", expression = "java( eu.openaire.api.mappers.Utils.formatSortByParam(src.getSortBy(), sortFieldMapping) )") SolrQueryParams toSolrQuery(ResearchProductsRequest src); @Named("calculateStart") diff --git a/src/main/java/eu/openaire/api/repositories/SolrRepository.java b/src/main/java/eu/openaire/api/repositories/SolrRepository.java index 7322678..7f9389f 100644 --- a/src/main/java/eu/openaire/api/repositories/SolrRepository.java +++ b/src/main/java/eu/openaire/api/repositories/SolrRepository.java @@ -1,6 +1,5 @@ package eu.openaire.api.repositories; -import eu.openaire.api.mappers.Utils; import eu.openaire.api.solr.SolrConnectionManager; import eu.openaire.api.solr.SolrQueryParams; import lombok.RequiredArgsConstructor; @@ -47,15 +46,8 @@ public class SolrRepository { query.setRows(queryParams.getRows()); // set sorting - if (!Utils.isNullOrEmpty(queryParams.getSort())) { - - String[] sortByPairs = queryParams.getSort().split(","); - for (String pair : sortByPairs) { - String[] parts = pair.trim().split("\\s+"); - String field = parts[0]; - SolrQuery.ORDER order = parts[1].equalsIgnoreCase("ASC") ? SolrQuery.ORDER.asc : SolrQuery.ORDER.desc; - query.addSort(field, order); - } + for (var sortClause : queryParams.getSort()) { + query.addSort(sortClause); } log.info(query); diff --git a/src/main/java/eu/openaire/api/solr/SolrQueryParams.java b/src/main/java/eu/openaire/api/solr/SolrQueryParams.java index 801e7bf..c5ad118 100644 --- a/src/main/java/eu/openaire/api/solr/SolrQueryParams.java +++ b/src/main/java/eu/openaire/api/solr/SolrQueryParams.java @@ -1,6 +1,7 @@ package eu.openaire.api.solr; import lombok.Data; +import org.apache.solr.client.solrj.SolrQuery; import java.util.List; @@ -17,6 +18,6 @@ public class SolrQueryParams { int rows; - String sort; + List sort; }