Fixed problems with results of chunked queries being incorrectly sorted.

This commit is contained in:
ianmarshall 2020-05-26 18:09:54 -04:00
parent b250ac4f3d
commit 5cc77b78d4
4 changed files with 62 additions and 8 deletions

View File

@ -20,14 +20,27 @@ package ca.uhn.fhir.jpa.dao;
* #L%
*/
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoObservation;
import ca.uhn.fhir.jpa.partition.IRequestPartitionHelperSvc;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.api.server.*;
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
import ca.uhn.fhir.rest.param.ReferenceParam;
import org.hl7.fhir.instance.model.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
public abstract class BaseHapiFhirResourceDaoObservation<T extends IBaseResource> extends BaseHapiFhirResourceDao<T> implements IFhirResourceDaoObservation<T> {
@Autowired
private IRequestPartitionHelperSvc myRequestPartitionHelperService;
protected void updateSearchParamsForLastn(SearchParameterMap theSearchParameterMap, RequestDetails theRequestDetails) {
if (!isPagingProviderDatabaseBacked(theRequestDetails)) {
theSearchParameterMap.setLoadSynchronous(true);
@ -37,12 +50,51 @@ public abstract class BaseHapiFhirResourceDaoObservation<T extends IBaseResource
SortSpec effectiveDtm = new SortSpec(getEffectiveParamName()).setOrder(SortOrderEnum.DESC);
SortSpec observationCode = new SortSpec(getCodeParamName()).setOrder(SortOrderEnum.ASC).setChain(effectiveDtm);
if(theSearchParameterMap.containsKey(getSubjectParamName()) || theSearchParameterMap.containsKey(getPatientParamName())) {
fixSubjectParamsOrderForLastn(theSearchParameterMap, theRequestDetails);
theSearchParameterMap.setSort(new SortSpec(getSubjectParamName()).setOrder(SortOrderEnum.ASC).setChain(observationCode));
} else {
theSearchParameterMap.setSort(observationCode);
}
}
private void fixSubjectParamsOrderForLastn(SearchParameterMap theSearchParameterMap, RequestDetails theRequestDetails) {
// Need to ensure that the patient/subject parameters are sorted in the SearchParameterMap to ensure correct ordering of
// the output. The reason for this is that observations are indexed by patient/subject forced ID, but then ordered in the
// final result set by subject/patient resource PID.
TreeMap<Long, IQueryParameterType> orderedSubjectReferenceMap = new TreeMap<>();
if(theSearchParameterMap.containsKey(getSubjectParamName())) {
RequestPartitionId requestPartitionId = myRequestPartitionHelperService.determineReadPartitionForRequest(theRequestDetails, getResourceName());
List<List<IQueryParameterType>> patientParams = new ArrayList<>();
if (theSearchParameterMap.get(getPatientParamName()) != null) {
patientParams.addAll(theSearchParameterMap.get(getPatientParamName()));
}
if (theSearchParameterMap.get(getSubjectParamName()) != null) {
patientParams.addAll(theSearchParameterMap.get(getSubjectParamName()));
}
for (List<? extends IQueryParameterType> nextPatientList : patientParams) {
for (IQueryParameterType nextOr : nextPatientList) {
if (nextOr instanceof ReferenceParam) {
ReferenceParam ref = (ReferenceParam) nextOr;
ResourcePersistentId pid = myIdHelperService.resolveResourcePersistentIds(requestPartitionId, ref.getResourceType(), ref.getIdPart());
orderedSubjectReferenceMap.put(pid.getIdAsLong(), nextOr);
} else {
throw new IllegalArgumentException("Invalid token type (expecting ReferenceParam): " + nextOr.getClass());
}
}
}
theSearchParameterMap.remove(getSubjectParamName());
theSearchParameterMap.remove(getPatientParamName());
for (Long subjectPid : orderedSubjectReferenceMap.keySet()) {
theSearchParameterMap.add(getSubjectParamName(), orderedSubjectReferenceMap.get(subjectPid));
}
}
}
abstract protected String getEffectiveParamName();
abstract protected String getCodeParamName();
abstract protected String getSubjectParamName();

View File

@ -32,6 +32,7 @@ import org.shadehapi.elasticsearch.search.SearchHits;
import org.shadehapi.elasticsearch.search.aggregations.AggregationBuilder;
import org.shadehapi.elasticsearch.search.aggregations.AggregationBuilders;
import org.shadehapi.elasticsearch.search.aggregations.Aggregations;
import org.shadehapi.elasticsearch.search.aggregations.BucketOrder;
import org.shadehapi.elasticsearch.search.aggregations.bucket.composite.*;
import org.shadehapi.elasticsearch.search.aggregations.bucket.terms.ParsedTerms;
import org.shadehapi.elasticsearch.search.aggregations.bucket.terms.Terms;
@ -44,7 +45,6 @@ import org.shadehapi.elasticsearch.search.sort.SortOrder;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;
import java.util.function.Function;
import static org.apache.commons.lang3.StringUtils.isBlank;
@ -149,9 +149,6 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
" \"type\" : \"keyword\",\n" +
" \"store\" : true\n" +
" },\n" +
" \"codeable_concept_text\" : {\n" +
" \"type\" : \"text\"\n" +
" },\n" +
" \"codingcode\" : {\n" +
" \"type\" : \"keyword\"\n" +
" },\n" +
@ -163,6 +160,9 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
" },\n" +
" \"codingsystem\" : {\n" +
" \"type\" : \"keyword\"\n" +
" },\n" +
" \"text\" : {\n" +
" \"type\" : \"text\"\n" +
" }\n" +
" }\n" +
" }\n" +
@ -247,8 +247,8 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
return subjectReferenceCriteria;
}
private TreeSet<String> getReferenceValues(List<? extends IQueryParameterType> referenceParams) {
TreeSet<String> referenceList = new TreeSet<>();
private List<String> getReferenceValues(List<? extends IQueryParameterType> referenceParams) {
List<String> referenceList = new ArrayList<>();
for (IQueryParameterType nextOr : referenceParams) {
@ -277,12 +277,14 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
private TermsAggregationBuilder createObservationCodeAggregationBuilder(int theMaxNumberObservationsPerCode, String[] theTopHitsInclude) {
TermsAggregationBuilder observationCodeCodeAggregationBuilder = new TermsAggregationBuilder(GROUP_BY_CODE, ValueType.STRING).field("codeconceptcodingcode");
observationCodeCodeAggregationBuilder.order(BucketOrder.key(true));
// Top Hits Aggregation
observationCodeCodeAggregationBuilder.subAggregation(AggregationBuilders.topHits("most_recent_effective")
.sort("effectivedtm", SortOrder.DESC)
.fetchSource(theTopHitsInclude, null).size(theMaxNumberObservationsPerCode));
observationCodeCodeAggregationBuilder.size(10000);
TermsAggregationBuilder observationCodeSystemAggregationBuilder = new TermsAggregationBuilder(GROUP_BY_SYSTEM, ValueType.STRING).field("codeconceptcodingsystem");
observationCodeSystemAggregationBuilder.order(BucketOrder.key(true));
observationCodeSystemAggregationBuilder.subAggregation(observationCodeCodeAggregationBuilder);
return observationCodeSystemAggregationBuilder;
}

View File

@ -27,7 +27,7 @@ public class CodeJson {
@JsonProperty(value = "codeable_concept_id", required = false)
private String myCodeableConceptId;
@JsonProperty(value = "codeable_concept_text", required = false)
@JsonProperty(value = "text", required = false)
private String myCodeableConceptText;
@JsonProperty(value = "codingcode", required = false)

View File

@ -15,7 +15,7 @@ import java.util.concurrent.TimeUnit;
@Configuration
public class TestElasticsearchConfig {
private final String elasticsearchHost = "127.0.0.1";
private final String elasticsearchHost = "localhost";
private final String elasticsearchUserId = "";
private final String elasticsearchPassword = "";