Add debugQuery parameter

This commit is contained in:
Serafeim Chatzopoulos 2024-06-21 16:08:10 +03:00
parent f146ebf79e
commit 8f81bd633c
23 changed files with 84 additions and 47 deletions

View File

@ -3,6 +3,7 @@ package eu.openaire.api.controllers;
import eu.dnetlib.dhp.oa.model.graph.Datasource; import eu.dnetlib.dhp.oa.model.graph.Datasource;
import eu.openaire.api.dto.request.DataSourceRequest; import eu.openaire.api.dto.request.DataSourceRequest;
import eu.openaire.api.dto.request.validators.AllowableFieldsValidator; import eu.openaire.api.dto.request.validators.AllowableFieldsValidator;
import eu.openaire.api.dto.request.validators.Utils;
import eu.openaire.api.dto.response.SearchResponse; import eu.openaire.api.dto.response.SearchResponse;
import eu.openaire.api.errors.ErrorResponse; import eu.openaire.api.errors.ErrorResponse;
import eu.openaire.api.errors.exceptions.BadRequestException; import eu.openaire.api.errors.exceptions.BadRequestException;
@ -62,10 +63,10 @@ public class DataSourceController
@ApiResponse(responseCode = "500", content = { @Content(schema = @Schema(implementation = ErrorResponse.class), mediaType = "application/json") }) @ApiResponse(responseCode = "500", content = { @Content(schema = @Schema(implementation = ErrorResponse.class), mediaType = "application/json") })
}) })
@GetMapping(value = "") @GetMapping(value = "")
public Object search(@Valid @ParameterObject final DataSourceRequest request, BindingResult validationResult) { public SearchResponse<Datasource> search(@Valid @ParameterObject final DataSourceRequest request, BindingResult validationResult) {
if (validationResult.hasErrors()) { if (validationResult.hasErrors()) {
throw new BadRequestException(AllowableFieldsValidator.getErrorMessage(validationResult.getAllErrors())); throw new BadRequestException(Utils.getErrorMessage(validationResult.getAllErrors()));
} }
return dataSourceService.search(request); return dataSourceService.search(request);

View File

@ -3,6 +3,7 @@ package eu.openaire.api.controllers;
import eu.dnetlib.dhp.oa.model.graph.Organization; import eu.dnetlib.dhp.oa.model.graph.Organization;
import eu.openaire.api.dto.request.OrganizationRequest; import eu.openaire.api.dto.request.OrganizationRequest;
import eu.openaire.api.dto.request.validators.AllowableFieldsValidator; import eu.openaire.api.dto.request.validators.AllowableFieldsValidator;
import eu.openaire.api.dto.request.validators.Utils;
import eu.openaire.api.dto.response.SearchResponse; import eu.openaire.api.dto.response.SearchResponse;
import eu.openaire.api.errors.ErrorResponse; import eu.openaire.api.errors.ErrorResponse;
import eu.openaire.api.errors.exceptions.BadRequestException; import eu.openaire.api.errors.exceptions.BadRequestException;
@ -62,10 +63,10 @@ public class OrganizationController
@ApiResponse(responseCode = "500", content = { @Content(schema = @Schema(implementation = ErrorResponse.class), mediaType = "application/json") }) @ApiResponse(responseCode = "500", content = { @Content(schema = @Schema(implementation = ErrorResponse.class), mediaType = "application/json") })
}) })
@GetMapping(value = "") @GetMapping(value = "")
public Object search(@Valid @ParameterObject final OrganizationRequest request, BindingResult validationResult) { public SearchResponse<Organization> search(@Valid @ParameterObject final OrganizationRequest request, BindingResult validationResult) {
if (validationResult.hasErrors()) { if (validationResult.hasErrors()) {
throw new BadRequestException(AllowableFieldsValidator.getErrorMessage(validationResult.getAllErrors())); throw new BadRequestException(Utils.getErrorMessage(validationResult.getAllErrors()));
} }
return organizationService.search(request); return organizationService.search(request);

View File

@ -3,6 +3,7 @@ package eu.openaire.api.controllers;
import eu.dnetlib.dhp.oa.model.graph.Project; import eu.dnetlib.dhp.oa.model.graph.Project;
import eu.openaire.api.dto.request.ProjectRequest; import eu.openaire.api.dto.request.ProjectRequest;
import eu.openaire.api.dto.request.validators.AllowableFieldsValidator; import eu.openaire.api.dto.request.validators.AllowableFieldsValidator;
import eu.openaire.api.dto.request.validators.Utils;
import eu.openaire.api.dto.response.SearchResponse; import eu.openaire.api.dto.response.SearchResponse;
import eu.openaire.api.errors.ErrorResponse; import eu.openaire.api.errors.ErrorResponse;
import eu.openaire.api.errors.exceptions.BadRequestException; import eu.openaire.api.errors.exceptions.BadRequestException;
@ -62,10 +63,10 @@ public class ProjectController
@ApiResponse(responseCode = "500", content = { @Content(schema = @Schema(implementation = ErrorResponse.class), mediaType = "application/json") }) @ApiResponse(responseCode = "500", content = { @Content(schema = @Schema(implementation = ErrorResponse.class), mediaType = "application/json") })
}) })
@GetMapping(value = "") @GetMapping(value = "")
public Object search(@Valid @ParameterObject final ProjectRequest request, BindingResult validationResult) { public SearchResponse<Project> search(@Valid @ParameterObject final ProjectRequest request, BindingResult validationResult) {
if (validationResult.hasErrors()) { if (validationResult.hasErrors()) {
throw new BadRequestException(AllowableFieldsValidator.getErrorMessage(validationResult.getAllErrors())); throw new BadRequestException(Utils.getErrorMessage(validationResult.getAllErrors()));
} }
return projectService.search(request); return projectService.search(request);

View File

@ -4,6 +4,7 @@ import eu.dnetlib.dhp.oa.model.graph.GraphResult;
import eu.openaire.api.dto.request.ResearchProductsRequest; import eu.openaire.api.dto.request.ResearchProductsRequest;
import eu.openaire.api.dto.request.validators.AllowableFieldsValidator; import eu.openaire.api.dto.request.validators.AllowableFieldsValidator;
import eu.openaire.api.dto.request.validators.ResearchProductsRequestValidator; import eu.openaire.api.dto.request.validators.ResearchProductsRequestValidator;
import eu.openaire.api.dto.request.validators.Utils;
import eu.openaire.api.dto.response.SearchResponse; import eu.openaire.api.dto.response.SearchResponse;
import eu.openaire.api.errors.ErrorResponse; import eu.openaire.api.errors.ErrorResponse;
import eu.openaire.api.errors.exceptions.BadRequestException; import eu.openaire.api.errors.exceptions.BadRequestException;
@ -69,7 +70,7 @@ public class ResearchProductsController
public SearchResponse<GraphResult> search(@Valid @ParameterObject final ResearchProductsRequest request, BindingResult validationResult) { public SearchResponse<GraphResult> search(@Valid @ParameterObject final ResearchProductsRequest request, BindingResult validationResult) {
if (validationResult.hasErrors()) { if (validationResult.hasErrors()) {
throw new BadRequestException(AllowableFieldsValidator.getErrorMessage(validationResult.getAllErrors())); throw new BadRequestException(Utils.getErrorMessage(validationResult.getAllErrors()));
} }
return researchProductService.search(request); return researchProductService.search(request);

View File

@ -84,6 +84,12 @@ public class DataSourceRequest {
) )
private String[] relCollectedFromDatasourceId; private String[] relCollectedFromDatasourceId;
@Parameter(
description = "Retrieve debug information for the search query",
schema = @Schema(type = "boolean", defaultValue = "true")
)
private Boolean debugQuery;
@Min(value = 1) @Min(value = 1)
@Parameter( @Parameter(
description = "Page number of the results", description = "Page number of the results",

View File

@ -63,6 +63,12 @@ public class OrganizationRequest {
) )
private String[] relCollectedFromDatasourceId; private String[] relCollectedFromDatasourceId;
@Parameter(
description = "Retrieve debug information for the search query",
schema = @Schema(type = "boolean", defaultValue = "true")
)
private Boolean debugQuery;
@Min(value = 1) @Min(value = 1)
@Parameter( @Parameter(
description = "Page number of the results", description = "Page number of the results",

View File

@ -130,6 +130,12 @@ public class ProjectRequest {
) )
private String[] relCollectedFromDatasourceId; private String[] relCollectedFromDatasourceId;
@Parameter(
description = "Retrieve debug information for the search query",
schema = @Schema(type = "boolean", defaultValue = "true")
)
private Boolean debugQuery;
@Min(value = 1) @Min(value = 1)
@Parameter( @Parameter(
description = "Page number of the results", description = "Page number of the results",

View File

@ -285,6 +285,12 @@ public class ResearchProductsRequest {
) )
private String[] relCollectedFromDatasourceId; private String[] relCollectedFromDatasourceId;
@Parameter(
description = "Retrieve debug information for the search query",
schema = @Schema(type = "boolean", defaultValue = "true")
)
private Boolean debugQuery;
@Min(value = 1) @Min(value = 1)
@Parameter( @Parameter(
description = "Page number of the results", description = "Page number of the results",

View File

@ -5,14 +5,11 @@ import eu.openaire.api.dto.request.OrganizationRequest;
import eu.openaire.api.dto.request.ProjectRequest; import eu.openaire.api.dto.request.ProjectRequest;
import eu.openaire.api.dto.request.ResearchProductsRequest; import eu.openaire.api.dto.request.ResearchProductsRequest;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.validation.Errors; import org.springframework.validation.Errors;
import org.springframework.validation.ObjectError;
import org.springframework.validation.Validator; import org.springframework.validation.Validator;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -49,9 +46,4 @@ public class AllowableFieldsValidator implements Validator {
}); });
} }
public static String getErrorMessage(List<ObjectError> allErrors) {
return allErrors.stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.joining("\n"));
}
} }

View File

@ -18,7 +18,6 @@ public class ResearchProductsRequestValidator implements Validator {
allowableValues.put("bestOpenAccessRightLabel", Set.of("OPEN SOURCE", "OPEN", "EMBARGO", "RESTRICTED", "CLOSED", "UNKNOWN")); allowableValues.put("bestOpenAccessRightLabel", Set.of("OPEN SOURCE", "OPEN", "EMBARGO", "RESTRICTED", "CLOSED", "UNKNOWN"));
allowableValues.put("impactClasses", Set.of("C1", "C2", "C3", "C4", "C5")); allowableValues.put("impactClasses", Set.of("C1", "C2", "C3", "C4", "C5"));
allowableValues.put("openAccessColor", Set.of("bronze", "gold", "hybrid")); allowableValues.put("openAccessColor", Set.of("bronze", "gold", "hybrid"));
} }

View File

@ -1,8 +1,12 @@
package eu.openaire.api.dto.request.validators; package eu.openaire.api.dto.request.validators;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.Errors; import org.springframework.validation.Errors;
import org.springframework.validation.ObjectError;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
public class Utils { public class Utils {
@ -34,4 +38,11 @@ public class Utils {
} }
} }
} }
public static String getErrorMessage(List<ObjectError> allErrors) {
return allErrors.stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.joining("\n"));
}
} }

View File

@ -1,14 +1,14 @@
package eu.openaire.api.dto.response; package eu.openaire.api.dto.response;
import com.fasterxml.jackson.annotation.JsonInclude;
import eu.openaire.api.solr.SolrQueryParams; import eu.openaire.api.solr.SolrQueryParams;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@Data @Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class SearchHeader { public class SearchHeader {
@Schema(hidden = true) private SolrQueryParams debugQuery;
private SolrQueryParams queryParams;
private long numFound; private long numFound;
@ -16,4 +16,8 @@ public class SearchHeader {
private int queryTime; private int queryTime;
private int page;
private int pageSize;
} }

View File

@ -64,7 +64,7 @@ public interface DataSourceRequestMapper {
// form query string // form query string
if (!qList.isEmpty()) { if (!qList.isEmpty()) {
solrQueryParams.setQ(String.join(" AND ", qList)); solrQueryParams.setQueryString(String.join(" AND ", qList));
} }
// set FQ // set FQ
@ -107,7 +107,7 @@ public interface DataSourceRequestMapper {
fqList.add(String.format(solrFieldMapping.get("relCollectedFromDatasourceId"), Utils.escapeAndJoin(src.getRelCollectedFromDatasourceId(), "OR", false))); fqList.add(String.format(solrFieldMapping.get("relCollectedFromDatasourceId"), Utils.escapeAndJoin(src.getRelCollectedFromDatasourceId(), "OR", false)));
} }
solrQueryParams.setFq(fqList); solrQueryParams.setFilterQueries(fqList);
} }
} }

View File

@ -62,7 +62,7 @@ public interface OrganizationRequestMapper {
// form query string // form query string
if (!qList.isEmpty()) { if (!qList.isEmpty()) {
solrQueryParams.setQ(String.join(" AND ", qList)); solrQueryParams.setQueryString(String.join(" AND ", qList));
} }
// set FQ // set FQ
@ -94,7 +94,7 @@ public interface OrganizationRequestMapper {
fqList.add(String.format(solrFieldMapping.get("relCollectedFromDatasourceId"), Utils.escapeAndJoin(src.getRelCollectedFromDatasourceId(), "OR", false))); fqList.add(String.format(solrFieldMapping.get("relCollectedFromDatasourceId"), Utils.escapeAndJoin(src.getRelCollectedFromDatasourceId(), "OR", false)));
} }
solrQueryParams.setFq(fqList); solrQueryParams.setFilterQueries(fqList);
} }
} }

View File

@ -74,7 +74,7 @@ public interface ProjectRequestMapper {
// form query string // form query string
if (!qList.isEmpty()) { if (!qList.isEmpty()) {
solrQueryParams.setQ(String.join(" AND ", qList)); solrQueryParams.setQueryString(String.join(" AND ", qList));
} }
// set FQ // set FQ
@ -148,7 +148,7 @@ public interface ProjectRequestMapper {
) )
).ifPresent(fqList::add); ).ifPresent(fqList::add);
solrQueryParams.setFq(fqList); solrQueryParams.setFilterQueries(fqList);
} }

View File

@ -117,7 +117,7 @@ public interface ResearchProductsRequestMapper {
// form query string // form query string
if (!qList.isEmpty()) { if (!qList.isEmpty()) {
solrQueryParams.setQ(String.join(" AND ", qList)); solrQueryParams.setQueryString(String.join(" AND ", qList));
} }
// set FQ // set FQ
@ -281,7 +281,7 @@ public interface ResearchProductsRequestMapper {
) )
).ifPresent(fqList::add); ).ifPresent(fqList::add);
solrQueryParams.setFq(fqList); solrQueryParams.setFilterQueries(fqList);
} }
} }

View File

@ -11,8 +11,11 @@ public interface ResponseHeaderMapper {
@Mapping(target = "numFound", source = "queryResponse.results.numFound") @Mapping(target = "numFound", source = "queryResponse.results.numFound")
@Mapping(target = "maxScore", source = "queryResponse.results.maxScore") @Mapping(target = "maxScore", source = "queryResponse.results.maxScore")
@Mapping(target = "page", source = "page")
@Mapping(target = "pageSize", source = "pageSize")
@Mapping(target = "queryTime", expression = "java( (int) queryResponse.getHeader().get(\"QTime\") )") @Mapping(target = "queryTime", expression = "java( (int) queryResponse.getHeader().get(\"QTime\") )")
@Mapping(target = "queryParams", source = "solrQueryParams") @Mapping(target = "debugQuery", expression = "java( (debugQuery) ? solrQueryParams : null )")
SearchHeader toSearchHeader(QueryResponse queryResponse, SolrQueryParams solrQueryParams); SearchHeader toSearchHeader(QueryResponse queryResponse, SolrQueryParams solrQueryParams,
boolean debugQuery, int page, int pageSize);
} }

View File

@ -31,15 +31,15 @@ public class SolrRepository {
SolrQuery query = new SolrQuery(); SolrQuery query = new SolrQuery();
// add Q // add Q
query.setQuery(queryParams.getQ()); query.setQuery(queryParams.getQueryString());
// add FQ // add FQ
for (String fq : queryParams.getFq()) { for (String fq : queryParams.getFilterQueries()) {
query.addFilterQuery(fq); query.addFilterQuery(fq);
} }
// add FL // add FL
query.addField(queryParams.getFl()); query.addField(queryParams.getFieldList());
// set pagination parameters // set pagination parameters
query.setStart(queryParams.getStart()); query.setStart(queryParams.getStart());

View File

@ -52,14 +52,14 @@ public class DataSourceService {
SolrQueryParams solrQueryParams = dataSourceRequestMapper.toSolrQuery(request); SolrQueryParams solrQueryParams = dataSourceRequestMapper.toSolrQuery(request);
// TODO: debug log here log.debug(solrQueryParams);
log.info(solrQueryParams);
// format the header response // format the header response
QueryResponse queryResponse = solrRepository.query(solrQueryParams); QueryResponse queryResponse = solrRepository.query(solrQueryParams);
// format the result documents // format the result documents
SearchHeader searchHeader = responseHeaderMapper.toSearchHeader(queryResponse, solrQueryParams); SearchHeader searchHeader = responseHeaderMapper.toSearchHeader(queryResponse, solrQueryParams,
request.getDebugQuery(), request.getPage(), request.getPageSize());
// format the result documents // format the result documents
List<Datasource> results = responseResultsMapper.toSearchResults(queryResponse, datasourceMapper::toGraphDatasource); List<Datasource> results = responseResultsMapper.toSearchResults(queryResponse, datasourceMapper::toGraphDatasource);

View File

@ -52,14 +52,14 @@ public class OrganizationService {
SolrQueryParams solrQueryParams = organizationRequestMapper.toSolrQuery(request); SolrQueryParams solrQueryParams = organizationRequestMapper.toSolrQuery(request);
// TODO: debug log here log.debug(solrQueryParams);
log.info(solrQueryParams);
// format the header response // format the header response
QueryResponse queryResponse = solrRepository.query(solrQueryParams); QueryResponse queryResponse = solrRepository.query(solrQueryParams);
// format the result documents // format the result documents
SearchHeader searchHeader = responseHeaderMapper.toSearchHeader(queryResponse, solrQueryParams); SearchHeader searchHeader = responseHeaderMapper.toSearchHeader(queryResponse, solrQueryParams,
request.getDebugQuery(), request.getPage(), request.getPageSize());
// format the result documents // format the result documents
List<Organization> results = responseResultsMapper.toSearchResults(queryResponse, organizationMapper::toGraphOrganization); List<Organization> results = responseResultsMapper.toSearchResults(queryResponse, organizationMapper::toGraphOrganization);

View File

@ -52,14 +52,14 @@ public class ProjectService {
SolrQueryParams solrQueryParams = projectRequestMapper.toSolrQuery(request); SolrQueryParams solrQueryParams = projectRequestMapper.toSolrQuery(request);
// TODO: debug log here log.debug(solrQueryParams);
log.info(solrQueryParams);
// perform the query // perform the query
QueryResponse queryResponse = solrRepository.query(solrQueryParams); QueryResponse queryResponse = solrRepository.query(solrQueryParams);
// format the header response // format the header response
SearchHeader searchHeader = responseHeaderMapper.toSearchHeader(queryResponse, solrQueryParams); SearchHeader searchHeader = responseHeaderMapper.toSearchHeader(queryResponse, solrQueryParams,
request.getDebugQuery(), request.getPage(), request.getPageSize());
// format the result documents // format the result documents
List<Project> results = responseResultsMapper.toSearchResults(queryResponse, projectMapper::toGraphProject); List<Project> results = responseResultsMapper.toSearchResults(queryResponse, projectMapper::toGraphProject);

View File

@ -53,14 +53,14 @@ public class ResearchProductService {
SolrQueryParams solrQueryParams = researchProductsRequestMapper.toSolrQuery(request); SolrQueryParams solrQueryParams = researchProductsRequestMapper.toSolrQuery(request);
// TODO: debug log here log.debug(solrQueryParams);
log.info(solrQueryParams);
// perform the query // perform the query
QueryResponse queryResponse = solrRepository.query(solrQueryParams); QueryResponse queryResponse = solrRepository.query(solrQueryParams);
// format the header response // format the header response
SearchHeader searchHeader = responseHeaderMapper.toSearchHeader(queryResponse, solrQueryParams); SearchHeader searchHeader = responseHeaderMapper.toSearchHeader(queryResponse, solrQueryParams,
request.getDebugQuery(), request.getPage(), request.getPageSize());
// format the result documents // format the result documents
List<GraphResult> results = responseResultsMapper.toSearchResults(queryResponse, researchProductMapper::toGraphResult); List<GraphResult> results = responseResultsMapper.toSearchResults(queryResponse, researchProductMapper::toGraphResult);

View File

@ -8,11 +8,11 @@ import java.util.List;
@Data @Data
public class SolrQueryParams { public class SolrQueryParams {
String q = "*:*"; String queryString = "*:*";
List<String> fq; List<String> filterQueries;
String fl = "__json"; String fieldList = "__json";
int start; int start;