Fixed sorting with chunked and paged queries.
This commit is contained in:
parent
529e1e1f5e
commit
6a27192a96
|
@ -585,6 +585,11 @@
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
<classifier>shaded6</classifier>
|
<classifier>shaded6</classifier>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.postgresql</groupId>
|
||||||
|
<artifactId>postgresql</artifactId>
|
||||||
|
<version>42.2.9</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ package ca.uhn.fhir.jpa.dao;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoObservation;
|
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoObservation;
|
||||||
import ca.uhn.fhir.jpa.search.lastn.IndexConstants;
|
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
import ca.uhn.fhir.rest.api.*;
|
import ca.uhn.fhir.rest.api.*;
|
||||||
import ca.uhn.fhir.rest.api.server.*;
|
import ca.uhn.fhir.rest.api.server.*;
|
||||||
|
@ -35,12 +34,18 @@ public abstract class BaseHapiFhirResourceDaoObservation<T extends IBaseResource
|
||||||
}
|
}
|
||||||
|
|
||||||
theSearchParameterMap.setLastN(true);
|
theSearchParameterMap.setLastN(true);
|
||||||
if (theSearchParameterMap.getSort() == null) {
|
SortSpec effectiveDtm = new SortSpec(getEffectiveParamName()).setOrder(SortOrderEnum.DESC);
|
||||||
SortSpec effectiveDtm = new SortSpec("date").setOrder(SortOrderEnum.DESC);
|
SortSpec observationCode = new SortSpec(getCodeParamName()).setOrder(SortOrderEnum.ASC).setChain(effectiveDtm);
|
||||||
// TODO: Should probably remove these constants, maybe move this logic to the version-specific classes.
|
if(theSearchParameterMap.containsKey(getSubjectParamName()) || theSearchParameterMap.containsKey(getPatientParamName())) {
|
||||||
SortSpec observationCode = new SortSpec(IndexConstants.CODE_SEARCH_PARAM).setOrder(SortOrderEnum.ASC).setChain(effectiveDtm);
|
theSearchParameterMap.setSort(new SortSpec(getSubjectParamName()).setOrder(SortOrderEnum.ASC).setChain(observationCode));
|
||||||
theSearchParameterMap.setSort(new SortSpec(IndexConstants.SUBJECT_SEARCH_PARAM).setOrder(SortOrderEnum.ASC).setChain(observationCode));
|
} else {
|
||||||
|
theSearchParameterMap.setSort(observationCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract protected String getEffectiveParamName();
|
||||||
|
abstract protected String getCodeParamName();
|
||||||
|
abstract protected String getSubjectParamName();
|
||||||
|
abstract protected String getPatientParamName();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -317,7 +317,7 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
} else {
|
} else {
|
||||||
throw new InvalidRequestException("Max parameter is required for $lastn operation");
|
throw new InvalidRequestException("Max parameter is required for $lastn operation");
|
||||||
}
|
}
|
||||||
List<String> lastnResourceIds = myIElasticsearchSvc.executeLastN(myParams, myMaxObservationsPerCode, theMaximumResults);
|
List<String> lastnResourceIds = myIElasticsearchSvc.executeLastN(myParams, myContext, theMaximumResults);
|
||||||
for (String lastnResourceId : lastnResourceIds) {
|
for (String lastnResourceId : lastnResourceIds) {
|
||||||
pids.add(myIdHelperService.resolveResourcePersistentIds(myRequestPartitionId, myResourceName, lastnResourceId));
|
pids.add(myIdHelperService.resolveResourcePersistentIds(myRequestPartitionId, myResourceName, lastnResourceId));
|
||||||
}
|
}
|
||||||
|
@ -422,52 +422,6 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
searchForIdsWithAndOr(myParams, theRequest);
|
searchForIdsWithAndOr(myParams, theRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Fulltext or lastn search
|
|
||||||
*/
|
|
||||||
/* if (myParams.containsKey(Constants.PARAM_CONTENT) || myParams.containsKey(Constants.PARAM_TEXT) || myParams.isLastN()) {
|
|
||||||
List<ResourcePersistentId> pids = new ArrayList<>();
|
|
||||||
if (myParams.containsKey(Constants.PARAM_CONTENT) || myParams.containsKey(Constants.PARAM_TEXT)) {
|
|
||||||
if (myFulltextSearchSvc == null) {
|
|
||||||
if (myParams.containsKey(Constants.PARAM_TEXT)) {
|
|
||||||
throw new InvalidRequestException("Fulltext search is not enabled on this service, can not process parameter: " + Constants.PARAM_TEXT);
|
|
||||||
} else if (myParams.containsKey(Constants.PARAM_CONTENT)) {
|
|
||||||
throw new InvalidRequestException("Fulltext search is not enabled on this service, can not process parameter: " + Constants.PARAM_CONTENT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (myParams.getEverythingMode() != null) {
|
|
||||||
pids = myFulltextSearchSvc.everything(myResourceName, myParams, theRequest);
|
|
||||||
} else {
|
|
||||||
pids = myFulltextSearchSvc.search(myResourceName, myParams);
|
|
||||||
}
|
|
||||||
} else if (myParams.isLastN()) {
|
|
||||||
if (myIElasticsearchSvc == null) {
|
|
||||||
if (myParams.isLastN()) {
|
|
||||||
throw new InvalidRequestException("LastN operation is not enabled on this service, can not process this request");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Integer myMaxObservationsPerCode = null;
|
|
||||||
if(myParams.getLastNMax() != null) {
|
|
||||||
myMaxObservationsPerCode = myParams.getLastNMax();
|
|
||||||
} else {
|
|
||||||
throw new InvalidRequestException("Max parameter is required for $lastn operation");
|
|
||||||
}
|
|
||||||
List<String> lastnResourceIds = myIElasticsearchSvc.executeLastN(myParams, myMaxObservationsPerCode);
|
|
||||||
for (String lastnResourceId : lastnResourceIds) {
|
|
||||||
pids.add(myIdHelperService.resolveResourcePersistentIds(myRequestPartitionId, myResourceName, lastnResourceId));
|
|
||||||
}
|
|
||||||
// pids = normalizeIdListForLastNInClause(lastnResourceIds);
|
|
||||||
}
|
|
||||||
if (pids.isEmpty()) {
|
|
||||||
// Will never match
|
|
||||||
pids = Collections.singletonList(new ResourcePersistentId(-1L));
|
|
||||||
}
|
|
||||||
|
|
||||||
myQueryRoot.addPredicate(myQueryRoot.get("myId").as(Long.class).in(ResourcePersistentId.toLongList(pids)));
|
|
||||||
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
// Add PID list predicate for full text search and/or lastn operation
|
// Add PID list predicate for full text search and/or lastn operation
|
||||||
if (thePidList != null && thePidList.size() > 0) {
|
if (thePidList != null && thePidList.size() > 0) {
|
||||||
myQueryRoot.addPredicate(myQueryRoot.get("myId").as(Long.class).in(thePidList));
|
myQueryRoot.addPredicate(myQueryRoot.get("myId").as(Long.class).in(thePidList));
|
||||||
|
|
|
@ -30,8 +30,6 @@ import ca.uhn.fhir.rest.api.Constants;
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
||||||
import ca.uhn.fhir.rest.param.ReferenceAndListParam;
|
|
||||||
import ca.uhn.fhir.rest.param.TokenAndListParam;
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.dstu3.model.Observation;
|
import org.hl7.fhir.dstu3.model.Observation;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
@ -52,6 +50,26 @@ public class FhirResourceDaoObservationDstu3 extends BaseHapiFhirResourceDaoObse
|
||||||
return mySearchCoordinatorSvc.registerSearch(this, theSearchParameterMap, getResourceName(), new CacheControlDirective().parse(theRequestDetails.getHeaders(Constants.HEADER_CACHE_CONTROL)), theRequestDetails);
|
return mySearchCoordinatorSvc.registerSearch(this, theSearchParameterMap, getResourceName(), new CacheControlDirective().parse(theRequestDetails.getHeaders(Constants.HEADER_CACHE_CONTROL)), theRequestDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getEffectiveParamName() {
|
||||||
|
return Observation.SP_DATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getCodeParamName() {
|
||||||
|
return Observation.SP_CODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getSubjectParamName() {
|
||||||
|
return Observation.SP_SUBJECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getPatientParamName() {
|
||||||
|
return Observation.SP_PATIENT;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||||
boolean theUpdateVersion, TransactionDetails theTransactionDetails, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
boolean theUpdateVersion, TransactionDetails theTransactionDetails, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||||
|
|
|
@ -57,6 +57,26 @@ public class FhirResourceDaoObservationR4 extends BaseHapiFhirResourceDaoObserva
|
||||||
return mySearchCoordinatorSvc.registerSearch(this, theSearchParameterMap, getResourceName(), new CacheControlDirective().parse(theRequestDetails.getHeaders(Constants.HEADER_CACHE_CONTROL)), theRequestDetails);
|
return mySearchCoordinatorSvc.registerSearch(this, theSearchParameterMap, getResourceName(), new CacheControlDirective().parse(theRequestDetails.getHeaders(Constants.HEADER_CACHE_CONTROL)), theRequestDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getEffectiveParamName() {
|
||||||
|
return Observation.SP_DATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getCodeParamName() {
|
||||||
|
return Observation.SP_CODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getSubjectParamName() {
|
||||||
|
return Observation.SP_SUBJECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getPatientParamName() {
|
||||||
|
return Observation.SP_PATIENT;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||||
boolean theUpdateVersion, TransactionDetails theTransactionDetails, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
boolean theUpdateVersion, TransactionDetails theTransactionDetails, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||||
|
|
|
@ -30,8 +30,6 @@ import ca.uhn.fhir.rest.api.Constants;
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
||||||
import ca.uhn.fhir.rest.param.ReferenceAndListParam;
|
|
||||||
import ca.uhn.fhir.rest.param.TokenAndListParam;
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.r5.model.Observation;
|
import org.hl7.fhir.r5.model.Observation;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
@ -52,6 +50,26 @@ public class FhirResourceDaoObservationR5 extends BaseHapiFhirResourceDaoObserva
|
||||||
return mySearchCoordinatorSvc.registerSearch(this, theSearchParameterMap, getResourceName(), new CacheControlDirective().parse(theRequestDetails.getHeaders(Constants.HEADER_CACHE_CONTROL)), theRequestDetails);
|
return mySearchCoordinatorSvc.registerSearch(this, theSearchParameterMap, getResourceName(), new CacheControlDirective().parse(theRequestDetails.getHeaders(Constants.HEADER_CACHE_CONTROL)), theRequestDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getEffectiveParamName() {
|
||||||
|
return Observation.SP_DATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getCodeParamName() {
|
||||||
|
return Observation.SP_CODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getSubjectParamName() {
|
||||||
|
return Observation.SP_SUBJECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getPatientParamName() {
|
||||||
|
return Observation.SP_PATIENT;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||||
boolean theUpdateVersion, TransactionDetails theTransactionDetails, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
boolean theUpdateVersion, TransactionDetails theTransactionDetails, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||||
|
|
|
@ -70,10 +70,7 @@ public class BaseJpaResourceProviderObservationDstu3 extends JpaResourceProvider
|
||||||
|
|
||||||
@Description(shortDefinition="The maximum number of observations to return for each observation code")
|
@Description(shortDefinition="The maximum number of observations to return for each observation code")
|
||||||
@OperationParam(name = "max", typeName = "integer", min = 0, max = 1)
|
@OperationParam(name = "max", typeName = "integer", min = 0, max = 1)
|
||||||
IPrimitiveType<Integer> theMax,
|
IPrimitiveType<Integer> theMax
|
||||||
|
|
||||||
@Sort
|
|
||||||
SortSpec theSort
|
|
||||||
|
|
||||||
) {
|
) {
|
||||||
startRequest(theServletRequest);
|
startRequest(theServletRequest);
|
||||||
|
@ -81,17 +78,17 @@ public class BaseJpaResourceProviderObservationDstu3 extends JpaResourceProvider
|
||||||
SearchParameterMap paramMap = new SearchParameterMap();
|
SearchParameterMap paramMap = new SearchParameterMap();
|
||||||
paramMap.add(Observation.SP_CATEGORY, theCategory);
|
paramMap.add(Observation.SP_CATEGORY, theCategory);
|
||||||
paramMap.add(Observation.SP_CODE, theCode);
|
paramMap.add(Observation.SP_CODE, theCode);
|
||||||
paramMap.add(Observation.SP_PATIENT, thePatient);
|
if (thePatient != null) {
|
||||||
paramMap.add(Observation.SP_SUBJECT, theSubject);
|
paramMap.add("patient", thePatient);
|
||||||
|
}
|
||||||
|
if (theSubject != null) {
|
||||||
|
paramMap.add("subject", theSubject);
|
||||||
|
}
|
||||||
paramMap.setLastNMax(theMax.getValue());
|
paramMap.setLastNMax(theMax.getValue());
|
||||||
if (theCount != null) {
|
if (theCount != null) {
|
||||||
paramMap.setCount(theCount.getValue());
|
paramMap.setCount(theCount.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theSort != null) {
|
|
||||||
paramMap.setSort(theSort);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((IFhirResourceDaoObservation<Observation>) getDao()).observationsLastN(paramMap, theRequestDetails, theServletResponse);
|
return ((IFhirResourceDaoObservation<Observation>) getDao()).observationsLastN(paramMap, theRequestDetails, theServletResponse);
|
||||||
} finally {
|
} finally {
|
||||||
endRequest(theServletRequest);
|
endRequest(theServletRequest);
|
||||||
|
|
|
@ -69,28 +69,25 @@ public class BaseJpaResourceProviderObservationR4 extends JpaResourceProviderR4<
|
||||||
|
|
||||||
@Description(shortDefinition="The maximum number of observations to return for each observation code")
|
@Description(shortDefinition="The maximum number of observations to return for each observation code")
|
||||||
@OperationParam(name = "max", typeName = "integer", min = 0, max = 1)
|
@OperationParam(name = "max", typeName = "integer", min = 0, max = 1)
|
||||||
IPrimitiveType<Integer> theMax,
|
IPrimitiveType<Integer> theMax
|
||||||
|
|
||||||
@Sort
|
|
||||||
SortSpec theSort
|
|
||||||
|
|
||||||
) {
|
) {
|
||||||
startRequest(theServletRequest);
|
startRequest(theServletRequest);
|
||||||
try {
|
try {
|
||||||
SearchParameterMap paramMap = new SearchParameterMap();
|
SearchParameterMap paramMap = new SearchParameterMap();
|
||||||
paramMap.add("category", theCategory);
|
paramMap.add(Observation.SP_CATEGORY, theCategory);
|
||||||
paramMap.add("code", theCode);
|
paramMap.add(Observation.SP_CODE, theCode);
|
||||||
paramMap.add("patient", thePatient);
|
if (thePatient != null) {
|
||||||
paramMap.add("subject", theSubject);
|
paramMap.add(Observation.SP_PATIENT, thePatient);
|
||||||
|
}
|
||||||
|
if (theSubject != null) {
|
||||||
|
paramMap.add(Observation.SP_SUBJECT, theSubject);
|
||||||
|
}
|
||||||
paramMap.setLastNMax(theMax.getValue());
|
paramMap.setLastNMax(theMax.getValue());
|
||||||
if (theCount != null) {
|
if (theCount != null) {
|
||||||
paramMap.setCount(theCount.getValue());
|
paramMap.setCount(theCount.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theSort != null) {
|
|
||||||
paramMap.setSort(theSort);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((IFhirResourceDaoObservation<Observation>) getDao()).observationsLastN(paramMap, theRequestDetails, theServletResponse);
|
return ((IFhirResourceDaoObservation<Observation>) getDao()).observationsLastN(paramMap, theRequestDetails, theServletResponse);
|
||||||
} finally {
|
} finally {
|
||||||
endRequest(theServletRequest);
|
endRequest(theServletRequest);
|
||||||
|
|
|
@ -70,28 +70,25 @@ public class BaseJpaResourceProviderObservationR5 extends JpaResourceProviderR5<
|
||||||
|
|
||||||
@Description(shortDefinition="The maximum number of observations to return for each observation code")
|
@Description(shortDefinition="The maximum number of observations to return for each observation code")
|
||||||
@OperationParam(name = "max", typeName = "integer", min = 0, max = 1)
|
@OperationParam(name = "max", typeName = "integer", min = 0, max = 1)
|
||||||
IPrimitiveType<Integer> theMax,
|
IPrimitiveType<Integer> theMax
|
||||||
|
|
||||||
@Sort
|
|
||||||
SortSpec theSort
|
|
||||||
|
|
||||||
) {
|
) {
|
||||||
startRequest(theServletRequest);
|
startRequest(theServletRequest);
|
||||||
try {
|
try {
|
||||||
SearchParameterMap paramMap = new SearchParameterMap();
|
SearchParameterMap paramMap = new SearchParameterMap();
|
||||||
paramMap.add("category", theCategory);
|
paramMap.add(Observation.SP_CATEGORY, theCategory);
|
||||||
paramMap.add("code", theCode);
|
paramMap.add(Observation.SP_CODE, theCode);
|
||||||
paramMap.add("patient", thePatient);
|
if (thePatient != null) {
|
||||||
paramMap.add("subject", theSubject);
|
paramMap.add(Observation.SP_PATIENT, thePatient);
|
||||||
|
}
|
||||||
|
if (theSubject != null) {
|
||||||
|
paramMap.add(Observation.SP_SUBJECT, theSubject);
|
||||||
|
}
|
||||||
paramMap.setLastNMax(theMax.getValue());
|
paramMap.setLastNMax(theMax.getValue());
|
||||||
if (theCount != null) {
|
if (theCount != null) {
|
||||||
paramMap.setCount(theCount.getValue());
|
paramMap.setCount(theCount.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theSort != null) {
|
|
||||||
paramMap.setSort(theSort);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((IFhirResourceDaoObservation<Observation>) getDao()).observationsLastN(paramMap, theRequestDetails, theServletResponse);
|
return ((IFhirResourceDaoObservation<Observation>) getDao()).observationsLastN(paramMap, theRequestDetails, theServletResponse);
|
||||||
} finally {
|
} finally {
|
||||||
endRequest(theServletRequest);
|
endRequest(theServletRequest);
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package ca.uhn.fhir.jpa.search.lastn;
|
package ca.uhn.fhir.jpa.search.lastn;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
|
import ca.uhn.fhir.jpa.searchparam.util.LastNParameterHelper;
|
||||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||||
import ca.uhn.fhir.rest.param.TokenParam;
|
import ca.uhn.fhir.rest.param.TokenParam;
|
||||||
|
@ -48,13 +50,18 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
|
|
||||||
public class ElasticsearchSvcImpl implements IElasticsearchSvc {
|
public class ElasticsearchSvcImpl implements IElasticsearchSvc {
|
||||||
|
|
||||||
|
public static final String OBSERVATION_INDEX = "observation_index";
|
||||||
|
public static final String CODE_INDEX = "code_index";
|
||||||
|
public static final String OBSERVATION_DOCUMENT_TYPE = "ca.uhn.fhir.jpa.dao.lastn.entity.ObservationIndexedSearchParamLastNEntity";
|
||||||
|
public static final String CODE_DOCUMENT_TYPE = "ca.uhn.fhir.jpa.dao.lastn.entity.ObservationIndexedCodeCodeableConceptEntity";
|
||||||
|
|
||||||
private final RestHighLevelClient myRestHighLevelClient;
|
private final RestHighLevelClient myRestHighLevelClient;
|
||||||
|
|
||||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
private final String GROUP_BY_SUBJECT = "group_by_subject";
|
private final String GROUP_BY_SUBJECT = "group_by_subject";
|
||||||
|
private final String GROUP_BY_SYSTEM = "group_by_system";
|
||||||
private final String GROUP_BY_CODE = "group_by_code";
|
private final String GROUP_BY_CODE = "group_by_code";
|
||||||
private final String OBSERVATION_IDENTIFIER_FIELD_NAME = "identifier";
|
|
||||||
|
|
||||||
|
|
||||||
public ElasticsearchSvcImpl(String theHostname, int thePort, String theUsername, String thePassword) {
|
public ElasticsearchSvcImpl(String theHostname, int thePort, String theUsername, String thePassword) {
|
||||||
|
@ -69,7 +76,7 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createObservationIndexIfMissing() throws IOException {
|
private void createObservationIndexIfMissing() throws IOException {
|
||||||
if (indexExists(IndexConstants.OBSERVATION_INDEX)) {
|
if (indexExists(OBSERVATION_INDEX)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String observationMapping = "{\n" +
|
String observationMapping = "{\n" +
|
||||||
|
@ -124,14 +131,14 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
|
||||||
" }\n" +
|
" }\n" +
|
||||||
" }\n" +
|
" }\n" +
|
||||||
"}\n";
|
"}\n";
|
||||||
if (!createIndex(IndexConstants.OBSERVATION_INDEX, observationMapping)) {
|
if (!createIndex(OBSERVATION_INDEX, observationMapping)) {
|
||||||
throw new RuntimeException("Failed to create observation index");
|
throw new RuntimeException("Failed to create observation index");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createCodeIndexIfMissing() throws IOException {
|
private void createCodeIndexIfMissing() throws IOException {
|
||||||
if (indexExists(IndexConstants.CODE_INDEX)) {
|
if (indexExists(CODE_INDEX)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String codeMapping = "{\n" +
|
String codeMapping = "{\n" +
|
||||||
|
@ -161,7 +168,7 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
|
||||||
" }\n" +
|
" }\n" +
|
||||||
" }\n" +
|
" }\n" +
|
||||||
"}\n";
|
"}\n";
|
||||||
if (!createIndex(IndexConstants.CODE_INDEX, codeMapping)) {
|
if (!createIndex(CODE_INDEX, codeMapping)) {
|
||||||
throw new RuntimeException("Failed to create code index");
|
throw new RuntimeException("Failed to create code index");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,16 +206,18 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
// TODO: Should eliminate dependency on SearchParameterMap in API.
|
public List<String> executeLastN(SearchParameterMap theSearchParameterMap, FhirContext theFhirContext, Integer theMaxResultsToFetch) {
|
||||||
public List<String> executeLastN(SearchParameterMap theSearchParameterMap, Integer theMaxObservationsPerCode, Integer theMaxResultsToFetch) {
|
String OBSERVATION_IDENTIFIER_FIELD_NAME = "identifier";
|
||||||
String[] topHitsInclude = {OBSERVATION_IDENTIFIER_FIELD_NAME};
|
String[] topHitsInclude = {OBSERVATION_IDENTIFIER_FIELD_NAME};
|
||||||
try {
|
try {
|
||||||
List<SearchResponse> responses = buildAndExecuteSearch(theSearchParameterMap, theMaxObservationsPerCode, topHitsInclude);
|
List<SearchResponse> responses = buildAndExecuteSearch(theSearchParameterMap, theFhirContext, topHitsInclude);
|
||||||
List<String> observationIds = new ArrayList<>();
|
List<String> observationIds = new ArrayList<>();
|
||||||
for (SearchResponse response : responses) {
|
for (SearchResponse response : responses) {
|
||||||
// observationIds.addAll(buildObservationIdList(response));
|
Integer maxResultsToAdd = null;
|
||||||
Integer maxResultsToAdd = theMaxResultsToFetch - observationIds.size();
|
if (theMaxResultsToFetch != null) {
|
||||||
observationIds.addAll(buildObservationList(response, t -> t.getIdentifier(), theSearchParameterMap, maxResultsToAdd));
|
maxResultsToAdd = theMaxResultsToFetch - observationIds.size();
|
||||||
|
}
|
||||||
|
observationIds.addAll(buildObservationList(response, ObservationJson::getIdentifier, theSearchParameterMap, theFhirContext, maxResultsToAdd));
|
||||||
}
|
}
|
||||||
return observationIds;
|
return observationIds;
|
||||||
} catch (IOException theE) {
|
} catch (IOException theE) {
|
||||||
|
@ -216,23 +225,27 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<SearchResponse> buildAndExecuteSearch(SearchParameterMap theSearchParameterMap, Integer theMaxObservationsPerCode,
|
private List<SearchResponse> buildAndExecuteSearch(SearchParameterMap theSearchParameterMap, FhirContext theFhirContext,
|
||||||
String[] topHitsInclude) {
|
String[] topHitsInclude) {
|
||||||
List<SearchResponse> responses = new ArrayList<>();
|
List<SearchResponse> responses = new ArrayList<>();
|
||||||
if (theSearchParameterMap.containsKey(IndexConstants.PATIENT_SEARCH_PARAM) || theSearchParameterMap.containsKey(IndexConstants.SUBJECT_SEARCH_PARAM)) {
|
String patientParamName = LastNParameterHelper.getPatientParamName(theFhirContext);
|
||||||
|
String subjectParamName = LastNParameterHelper.getSubjectParamName(theFhirContext);
|
||||||
|
if (theSearchParameterMap.containsKey(patientParamName)
|
||||||
|
|| theSearchParameterMap.containsKey(subjectParamName)) {
|
||||||
ArrayList<String> subjectReferenceCriteria = new ArrayList<>();
|
ArrayList<String> subjectReferenceCriteria = new ArrayList<>();
|
||||||
List<List<IQueryParameterType>> patientParams = new ArrayList<>();
|
List<List<IQueryParameterType>> patientParams = new ArrayList<>();
|
||||||
if (theSearchParameterMap.get(IndexConstants.PATIENT_SEARCH_PARAM) != null) {
|
if (theSearchParameterMap.get(patientParamName) != null) {
|
||||||
patientParams.addAll(theSearchParameterMap.get(IndexConstants.PATIENT_SEARCH_PARAM));
|
patientParams.addAll(theSearchParameterMap.get(patientParamName));
|
||||||
}
|
}
|
||||||
if (theSearchParameterMap.get(IndexConstants.SUBJECT_SEARCH_PARAM) != null) {
|
if (theSearchParameterMap.get(subjectParamName) != null) {
|
||||||
patientParams.addAll(theSearchParameterMap.get(IndexConstants.SUBJECT_SEARCH_PARAM));
|
patientParams.addAll(theSearchParameterMap.get(subjectParamName));
|
||||||
}
|
}
|
||||||
for (List<? extends IQueryParameterType> nextSubjectList : patientParams) {
|
for (List<? extends IQueryParameterType> nextSubjectList : patientParams) {
|
||||||
subjectReferenceCriteria.addAll(getReferenceValues(nextSubjectList));
|
subjectReferenceCriteria.addAll(getReferenceValues(nextSubjectList));
|
||||||
}
|
}
|
||||||
for (String subject : subjectReferenceCriteria) {
|
for (String subject : subjectReferenceCriteria) {
|
||||||
SearchRequest myLastNRequest = buildObservationsSearchRequest(subject, theSearchParameterMap, createCompositeAggregationBuilder(theMaxObservationsPerCode, topHitsInclude));
|
SearchRequest myLastNRequest = buildObservationsSearchRequest(subject, theSearchParameterMap, theFhirContext,
|
||||||
|
createCompositeAggregationBuilder(theSearchParameterMap.getLastNMax(), topHitsInclude));
|
||||||
try {
|
try {
|
||||||
SearchResponse lastnResponse = executeSearchRequest(myLastNRequest);
|
SearchResponse lastnResponse = executeSearchRequest(myLastNRequest);
|
||||||
responses.add(lastnResponse);
|
responses.add(lastnResponse);
|
||||||
|
@ -241,7 +254,7 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SearchRequest myLastNRequest = buildObservationsSearchRequest(theSearchParameterMap, createObservationCodeAggregationBuilder(theMaxObservationsPerCode, topHitsInclude));
|
SearchRequest myLastNRequest = buildObservationsSearchRequest(theSearchParameterMap, theFhirContext, createObservationCodeAggregationBuilder(theSearchParameterMap.getLastNMax(), topHitsInclude));
|
||||||
try {
|
try {
|
||||||
SearchResponse lastnResponse = executeSearchRequest(myLastNRequest);
|
SearchResponse lastnResponse = executeSearchRequest(myLastNRequest);
|
||||||
responses.add(lastnResponse);
|
responses.add(lastnResponse);
|
||||||
|
@ -254,13 +267,12 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
// TODO: Should eliminate dependency on SearchParameterMap in API.
|
List<ObservationJson> executeLastNWithAllFields(SearchParameterMap theSearchParameterMap, FhirContext theFhirContext) {
|
||||||
List<ObservationJson> executeLastNWithAllFields(SearchParameterMap theSearchParameterMap, Integer theMaxObservationsPerCode, Integer theMaxResultsToFetch) {
|
|
||||||
try {
|
try {
|
||||||
List<SearchResponse> responses = buildAndExecuteSearch(theSearchParameterMap, theMaxObservationsPerCode, null);
|
List<SearchResponse> responses = buildAndExecuteSearch(theSearchParameterMap, theFhirContext, null);
|
||||||
List<ObservationJson> observationDocuments = new ArrayList<>();
|
List<ObservationJson> observationDocuments = new ArrayList<>();
|
||||||
for (SearchResponse response : responses) {
|
for (SearchResponse response : responses) {
|
||||||
observationDocuments.addAll(buildObservationList(response, t -> t, theSearchParameterMap, theMaxResultsToFetch));
|
observationDocuments.addAll(buildObservationList(response, t -> t, theSearchParameterMap, theFhirContext, 100));
|
||||||
}
|
}
|
||||||
return observationDocuments;
|
return observationDocuments;
|
||||||
} catch (IOException theE) {
|
} catch (IOException theE) {
|
||||||
|
@ -269,20 +281,15 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
List<CodeJson> queryAllIndexedObservationCodes(int theMaxResultSetSize) throws IOException {
|
List<CodeJson> queryAllIndexedObservationCodes() throws IOException {
|
||||||
SearchRequest codeSearchRequest = buildObservationCodesSearchRequest(theMaxResultSetSize);
|
SearchRequest codeSearchRequest = new SearchRequest(CODE_INDEX);
|
||||||
SearchResponse codeSearchResponse = executeSearchRequest(codeSearchRequest);
|
|
||||||
return buildCodeResult(codeSearchResponse);
|
|
||||||
}
|
|
||||||
|
|
||||||
private SearchRequest buildObservationCodesSearchRequest(int theMaxResultSetSize) {
|
|
||||||
SearchRequest searchRequest = new SearchRequest(IndexConstants.CODE_INDEX);
|
|
||||||
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
|
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
|
||||||
// Query
|
// Query
|
||||||
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
|
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
|
||||||
searchSourceBuilder.size(theMaxResultSetSize);
|
searchSourceBuilder.size(1000);
|
||||||
searchRequest.source(searchSourceBuilder);
|
codeSearchRequest.source(searchSourceBuilder);
|
||||||
return searchRequest;
|
SearchResponse codeSearchResponse = executeSearchRequest(codeSearchRequest);
|
||||||
|
return buildCodeResult(codeSearchResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompositeAggregationBuilder createCompositeAggregationBuilder(int theMaxNumberObservationsPerCode, String[] theTopHitsInclude) {
|
private CompositeAggregationBuilder createCompositeAggregationBuilder(int theMaxNumberObservationsPerCode, String[] theTopHitsInclude) {
|
||||||
|
@ -297,51 +304,27 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
|
||||||
}
|
}
|
||||||
|
|
||||||
private TermsAggregationBuilder createObservationCodeAggregationBuilder(int theMaxNumberObservationsPerCode, String[] theTopHitsInclude) {
|
private TermsAggregationBuilder createObservationCodeAggregationBuilder(int theMaxNumberObservationsPerCode, String[] theTopHitsInclude) {
|
||||||
TermsAggregationBuilder observationCodeAggregationBuilder = new TermsAggregationBuilder(GROUP_BY_CODE, ValueType.STRING).field("codeconceptid");
|
TermsAggregationBuilder observationCodeCodeAggregationBuilder = new TermsAggregationBuilder(GROUP_BY_CODE, ValueType.STRING).field("codeconceptcodingcode");
|
||||||
// Top Hits Aggregation
|
// Top Hits Aggregation
|
||||||
observationCodeAggregationBuilder.subAggregation(AggregationBuilders.topHits("most_recent_effective")
|
observationCodeCodeAggregationBuilder.subAggregation(AggregationBuilders.topHits("most_recent_effective")
|
||||||
.sort("effectivedtm", SortOrder.DESC)
|
.sort("effectivedtm", SortOrder.DESC)
|
||||||
.fetchSource(theTopHitsInclude, null).size(theMaxNumberObservationsPerCode));
|
.fetchSource(theTopHitsInclude, null).size(theMaxNumberObservationsPerCode));
|
||||||
observationCodeAggregationBuilder.size(10000);
|
observationCodeCodeAggregationBuilder.size(10000);
|
||||||
return observationCodeAggregationBuilder;
|
TermsAggregationBuilder observationCodeSystemAggregationBuilder = new TermsAggregationBuilder(GROUP_BY_SYSTEM, ValueType.STRING).field("codeconceptcodingsystem");
|
||||||
|
observationCodeSystemAggregationBuilder.subAggregation(observationCodeCodeAggregationBuilder);
|
||||||
|
return observationCodeSystemAggregationBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SearchResponse executeSearchRequest(SearchRequest searchRequest) throws IOException {
|
private SearchResponse executeSearchRequest(SearchRequest searchRequest) throws IOException {
|
||||||
return myRestHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
|
return myRestHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> buildObservationIdList(SearchResponse theSearchResponse) throws IOException {
|
|
||||||
List<String> theObservationList = new ArrayList<>();
|
|
||||||
for (ParsedComposite.ParsedBucket subjectBucket : getSubjectBuckets(theSearchResponse)) {
|
|
||||||
for (Terms.Bucket observationCodeBucket : getObservationCodeBuckets(subjectBucket)) {
|
|
||||||
for (SearchHit lastNMatch : getLastNMatches(observationCodeBucket)) {
|
|
||||||
String indexedObservation = lastNMatch.getSourceAsString();
|
|
||||||
ObservationJson observationJson = objectMapper.readValue(indexedObservation, ObservationJson.class);
|
|
||||||
theObservationList.add(observationJson.getIdentifier());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return theObservationList;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<ObservationJson> buildObservationDocumentList(SearchResponse theSearchResponse) throws IOException {
|
|
||||||
List<ObservationJson> theObservationList = new ArrayList<>();
|
|
||||||
for (ParsedComposite.ParsedBucket subjectBucket : getSubjectBuckets(theSearchResponse)) {
|
|
||||||
for (Terms.Bucket observationCodeBucket : getObservationCodeBuckets(subjectBucket)) {
|
|
||||||
for (SearchHit lastNMatch : getLastNMatches(observationCodeBucket)) {
|
|
||||||
String indexedObservation = lastNMatch.getSourceAsString();
|
|
||||||
ObservationJson observationJson = objectMapper.readValue(indexedObservation, ObservationJson.class);
|
|
||||||
theObservationList.add(observationJson);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return theObservationList;
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> List<T> buildObservationList(SearchResponse theSearchResponse, Function<ObservationJson,T> setValue,
|
private <T> List<T> buildObservationList(SearchResponse theSearchResponse, Function<ObservationJson,T> setValue,
|
||||||
SearchParameterMap theSearchParameterMap, Integer theMaxResultsToFetch) throws IOException {
|
SearchParameterMap theSearchParameterMap, FhirContext theFhirContext,
|
||||||
|
Integer theMaxResultsToFetch) throws IOException {
|
||||||
List<T> theObservationList = new ArrayList<>();
|
List<T> theObservationList = new ArrayList<>();
|
||||||
if (theSearchParameterMap.containsKey(IndexConstants.PATIENT_SEARCH_PARAM) || theSearchParameterMap.containsKey(IndexConstants.SUBJECT_SEARCH_PARAM)) {
|
if (theSearchParameterMap.containsKey(LastNParameterHelper.getPatientParamName(theFhirContext))
|
||||||
|
|| theSearchParameterMap.containsKey(LastNParameterHelper.getSubjectParamName(theFhirContext))) {
|
||||||
for (ParsedComposite.ParsedBucket subjectBucket : getSubjectBuckets(theSearchResponse)) {
|
for (ParsedComposite.ParsedBucket subjectBucket : getSubjectBuckets(theSearchResponse)) {
|
||||||
if (theMaxResultsToFetch != null && theObservationList.size() >= theMaxResultsToFetch) {
|
if (theMaxResultsToFetch != null && theObservationList.size() >= theMaxResultsToFetch) {
|
||||||
break;
|
break;
|
||||||
|
@ -387,14 +370,23 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
|
||||||
|
|
||||||
private List<? extends Terms.Bucket> getObservationCodeBuckets(SearchResponse theSearchResponse) {
|
private List<? extends Terms.Bucket> getObservationCodeBuckets(SearchResponse theSearchResponse) {
|
||||||
Aggregations responseAggregations = theSearchResponse.getAggregations();
|
Aggregations responseAggregations = theSearchResponse.getAggregations();
|
||||||
ParsedTerms aggregatedObservationCodes = responseAggregations.get(GROUP_BY_CODE);
|
return getObservationCodeBuckets(responseAggregations);
|
||||||
return aggregatedObservationCodes.getBuckets();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<? extends Terms.Bucket> getObservationCodeBuckets(ParsedComposite.ParsedBucket theSubjectBucket) {
|
private List<? extends Terms.Bucket> getObservationCodeBuckets(ParsedComposite.ParsedBucket theSubjectBucket) {
|
||||||
Aggregations observationCodeAggregations = theSubjectBucket.getAggregations();
|
Aggregations observationCodeSystemAggregations = theSubjectBucket.getAggregations();
|
||||||
ParsedTerms aggregatedObservationCodes = observationCodeAggregations.get(GROUP_BY_CODE);
|
return getObservationCodeBuckets(observationCodeSystemAggregations);
|
||||||
return aggregatedObservationCodes.getBuckets();
|
}
|
||||||
|
|
||||||
|
private List<? extends Terms.Bucket> getObservationCodeBuckets(Aggregations theObservationCodeSystemAggregations) {
|
||||||
|
List<Terms.Bucket> retVal = new ArrayList<>();
|
||||||
|
ParsedTerms aggregatedObservationCodeSystems = theObservationCodeSystemAggregations.get(GROUP_BY_SYSTEM);
|
||||||
|
for(Terms.Bucket observationCodeSystem : aggregatedObservationCodeSystems.getBuckets()) {
|
||||||
|
Aggregations observationCodeCodeAggregations = observationCodeSystem.getAggregations();
|
||||||
|
ParsedTerms aggregatedObservationCodeCodes = observationCodeCodeAggregations.get(GROUP_BY_CODE);
|
||||||
|
retVal.addAll(aggregatedObservationCodeCodes.getBuckets());
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SearchHit[] getLastNMatches(Terms.Bucket theObservationCodeBucket) {
|
private SearchHit[] getLastNMatches(Terms.Bucket theObservationCodeBucket) {
|
||||||
|
@ -413,17 +405,16 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
|
||||||
return codes;
|
return codes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SearchRequest buildObservationsSearchRequest(SearchParameterMap theSearchParameterMap, AggregationBuilder theAggregationBuilder) {
|
private SearchRequest buildObservationsSearchRequest(SearchParameterMap theSearchParameterMap, FhirContext theFhirContext, AggregationBuilder theAggregationBuilder) {
|
||||||
SearchRequest searchRequest = new SearchRequest(IndexConstants.OBSERVATION_INDEX);
|
SearchRequest searchRequest = new SearchRequest(OBSERVATION_INDEX);
|
||||||
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
|
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
|
||||||
// Query
|
// Query
|
||||||
if (!searchParamsHaveLastNCriteria(theSearchParameterMap)) {
|
if (!searchParamsHaveLastNCriteria(theSearchParameterMap, theFhirContext)) {
|
||||||
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
|
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
|
||||||
} else {
|
} else {
|
||||||
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
|
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
|
||||||
addSubjectsCriteria(boolQueryBuilder, theSearchParameterMap);
|
addCategoriesCriteria(boolQueryBuilder, theSearchParameterMap, theFhirContext);
|
||||||
addCategoriesCriteria(boolQueryBuilder, theSearchParameterMap);
|
addObservationCodeCriteria(boolQueryBuilder, theSearchParameterMap, theFhirContext);
|
||||||
addObservationCodeCriteria(boolQueryBuilder, theSearchParameterMap);
|
|
||||||
searchSourceBuilder.query(boolQueryBuilder);
|
searchSourceBuilder.query(boolQueryBuilder);
|
||||||
}
|
}
|
||||||
searchSourceBuilder.size(0);
|
searchSourceBuilder.size(0);
|
||||||
|
@ -435,14 +426,15 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
|
||||||
return searchRequest;
|
return searchRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SearchRequest buildObservationsSearchRequest(String theSubjectParam, SearchParameterMap theSearchParameterMap, AggregationBuilder theAggregationBuilder) {
|
private SearchRequest buildObservationsSearchRequest(String theSubjectParam, SearchParameterMap theSearchParameterMap, FhirContext theFhirContext,
|
||||||
SearchRequest searchRequest = new SearchRequest(IndexConstants.OBSERVATION_INDEX);
|
AggregationBuilder theAggregationBuilder) {
|
||||||
|
SearchRequest searchRequest = new SearchRequest(OBSERVATION_INDEX);
|
||||||
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
|
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
|
||||||
// Query
|
// Query
|
||||||
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
|
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
|
||||||
boolQueryBuilder.must(QueryBuilders.termQuery("subject", theSubjectParam));
|
boolQueryBuilder.must(QueryBuilders.termQuery("subject", theSubjectParam));
|
||||||
addCategoriesCriteria(boolQueryBuilder, theSearchParameterMap);
|
addCategoriesCriteria(boolQueryBuilder, theSearchParameterMap, theFhirContext);
|
||||||
addObservationCodeCriteria(boolQueryBuilder, theSearchParameterMap);
|
addObservationCodeCriteria(boolQueryBuilder, theSearchParameterMap, theFhirContext);
|
||||||
searchSourceBuilder.query(boolQueryBuilder);
|
searchSourceBuilder.query(boolQueryBuilder);
|
||||||
searchSourceBuilder.size(0);
|
searchSourceBuilder.size(0);
|
||||||
|
|
||||||
|
@ -453,30 +445,12 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
|
||||||
return searchRequest;
|
return searchRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Boolean searchParamsHaveLastNCriteria(SearchParameterMap theSearchParameterMap) {
|
private Boolean searchParamsHaveLastNCriteria(SearchParameterMap theSearchParameterMap, FhirContext theFhirContext) {
|
||||||
return theSearchParameterMap != null &&
|
return theSearchParameterMap != null &&
|
||||||
(theSearchParameterMap.containsKey(IndexConstants.PATIENT_SEARCH_PARAM) || theSearchParameterMap.containsKey(IndexConstants.SUBJECT_SEARCH_PARAM) ||
|
(theSearchParameterMap.containsKey(LastNParameterHelper.getPatientParamName(theFhirContext))
|
||||||
theSearchParameterMap.containsKey(IndexConstants.CATEGORY_SEARCH_PARAM) || theSearchParameterMap.containsKey(IndexConstants.CODE_SEARCH_PARAM));
|
|| theSearchParameterMap.containsKey(LastNParameterHelper.getSubjectParamName(theFhirContext))
|
||||||
}
|
|| theSearchParameterMap.containsKey(LastNParameterHelper.getCategoryParamName(theFhirContext))
|
||||||
|
|| theSearchParameterMap.containsKey(LastNParameterHelper.getCodeParamName(theFhirContext)));
|
||||||
private void addSubjectsCriteria(BoolQueryBuilder theBoolQueryBuilder, SearchParameterMap theSearchParameterMap) {
|
|
||||||
if (theSearchParameterMap.containsKey(IndexConstants.PATIENT_SEARCH_PARAM) || theSearchParameterMap.containsKey(IndexConstants.SUBJECT_SEARCH_PARAM)) {
|
|
||||||
ArrayList<String> subjectReferenceCriteria = new ArrayList<>();
|
|
||||||
List<List<IQueryParameterType>> andOrParams = new ArrayList<>();
|
|
||||||
if (theSearchParameterMap.get(IndexConstants.PATIENT_SEARCH_PARAM) != null) {
|
|
||||||
andOrParams.addAll(theSearchParameterMap.get(IndexConstants.PATIENT_SEARCH_PARAM));
|
|
||||||
}
|
|
||||||
if (theSearchParameterMap.get(IndexConstants.SUBJECT_SEARCH_PARAM) != null) {
|
|
||||||
andOrParams.addAll(theSearchParameterMap.get(IndexConstants.SUBJECT_SEARCH_PARAM));
|
|
||||||
}
|
|
||||||
for (List<? extends IQueryParameterType> nextAnd : andOrParams) {
|
|
||||||
subjectReferenceCriteria.addAll(getReferenceValues(nextAnd));
|
|
||||||
}
|
|
||||||
if (subjectReferenceCriteria.size() > 0) {
|
|
||||||
theBoolQueryBuilder.must(QueryBuilders.termsQuery("subject", subjectReferenceCriteria));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> getReferenceValues(List<? extends IQueryParameterType> referenceParams) {
|
private List<String> getReferenceValues(List<? extends IQueryParameterType> referenceParams) {
|
||||||
|
@ -496,13 +470,14 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
|
||||||
return referenceList;
|
return referenceList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCategoriesCriteria(BoolQueryBuilder theBoolQueryBuilder, SearchParameterMap theSearchParameterMap) {
|
private void addCategoriesCriteria(BoolQueryBuilder theBoolQueryBuilder, SearchParameterMap theSearchParameterMap, FhirContext theFhirContext) {
|
||||||
if (theSearchParameterMap.containsKey(IndexConstants.CATEGORY_SEARCH_PARAM)) {
|
String categoryParamName = LastNParameterHelper.getCategoryParamName(theFhirContext);
|
||||||
|
if (theSearchParameterMap.containsKey(categoryParamName)) {
|
||||||
ArrayList<String> codeSystemHashList = new ArrayList<>();
|
ArrayList<String> codeSystemHashList = new ArrayList<>();
|
||||||
ArrayList<String> codeOnlyList = new ArrayList<>();
|
ArrayList<String> codeOnlyList = new ArrayList<>();
|
||||||
ArrayList<String> systemOnlyList = new ArrayList<>();
|
ArrayList<String> systemOnlyList = new ArrayList<>();
|
||||||
ArrayList<String> textOnlyList = new ArrayList<>();
|
ArrayList<String> textOnlyList = new ArrayList<>();
|
||||||
List<List<IQueryParameterType>> andOrParams = theSearchParameterMap.get(IndexConstants.CATEGORY_SEARCH_PARAM);
|
List<List<IQueryParameterType>> andOrParams = theSearchParameterMap.get(categoryParamName);
|
||||||
for (List<? extends IQueryParameterType> nextAnd : andOrParams) {
|
for (List<? extends IQueryParameterType> nextAnd : andOrParams) {
|
||||||
codeSystemHashList.addAll(getCodingCodeSystemValues(nextAnd));
|
codeSystemHashList.addAll(getCodingCodeSystemValues(nextAnd));
|
||||||
codeOnlyList.addAll(getCodingCodeOnlyValues(nextAnd));
|
codeOnlyList.addAll(getCodingCodeOnlyValues(nextAnd));
|
||||||
|
@ -593,13 +568,14 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
|
||||||
return textOnlyList;
|
return textOnlyList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addObservationCodeCriteria(BoolQueryBuilder theBoolQueryBuilder, SearchParameterMap theSearchParameterMap) {
|
private void addObservationCodeCriteria(BoolQueryBuilder theBoolQueryBuilder, SearchParameterMap theSearchParameterMap, FhirContext theFhirContext) {
|
||||||
if (theSearchParameterMap.containsKey(IndexConstants.CODE_SEARCH_PARAM)) {
|
String codeParamName = LastNParameterHelper.getCodeParamName(theFhirContext);
|
||||||
|
if (theSearchParameterMap.containsKey(codeParamName)) {
|
||||||
ArrayList<String> codeSystemHashList = new ArrayList<>();
|
ArrayList<String> codeSystemHashList = new ArrayList<>();
|
||||||
ArrayList<String> codeOnlyList = new ArrayList<>();
|
ArrayList<String> codeOnlyList = new ArrayList<>();
|
||||||
ArrayList<String> systemOnlyList = new ArrayList<>();
|
ArrayList<String> systemOnlyList = new ArrayList<>();
|
||||||
ArrayList<String> textOnlyList = new ArrayList<>();
|
ArrayList<String> textOnlyList = new ArrayList<>();
|
||||||
List<List<IQueryParameterType>> andOrParams = theSearchParameterMap.get(IndexConstants.CODE_SEARCH_PARAM);
|
List<List<IQueryParameterType>> andOrParams = theSearchParameterMap.get(codeParamName);
|
||||||
for (List<? extends IQueryParameterType> nextAnd : andOrParams) {
|
for (List<? extends IQueryParameterType> nextAnd : andOrParams) {
|
||||||
codeSystemHashList.addAll(getCodingCodeSystemValues(nextAnd));
|
codeSystemHashList.addAll(getCodingCodeSystemValues(nextAnd));
|
||||||
codeOnlyList.addAll(getCodingCodeOnlyValues(nextAnd));
|
codeOnlyList.addAll(getCodingCodeOnlyValues(nextAnd));
|
||||||
|
@ -634,12 +610,4 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
|
||||||
myRestHighLevelClient.deleteByQuery(deleteByQueryRequest, RequestOptions.DEFAULT);
|
myRestHighLevelClient.deleteByQuery(deleteByQueryRequest, RequestOptions.DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* public void deleteObservationIndex(String theObservationIdentifier) throws IOException {
|
|
||||||
DeleteByQueryRequest deleteByQueryRequest = new DeleteByQueryRequest(IndexConstants.OBSERVATION_DOCUMENT_TYPE);
|
|
||||||
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
|
|
||||||
boolQueryBuilder.must(QueryBuilders.termsQuery(OBSERVATION_IDENTIFIER_FIELD_NAME, theObservationIdentifier));
|
|
||||||
deleteByQueryRequest.setQuery(boolQueryBuilder);
|
|
||||||
myRestHighLevelClient.deleteByQuery(deleteByQueryRequest, RequestOptions.DEFAULT);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
package ca.uhn.fhir.jpa.search.lastn;
|
package ca.uhn.fhir.jpa.search.lastn;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface IElasticsearchSvc {
|
public interface IElasticsearchSvc {
|
||||||
List<String> executeLastN(SearchParameterMap theSearchParameterMap, Integer theMaxObservationsPerCode, Integer theMaxResultsToFetch);
|
List<String> executeLastN(SearchParameterMap theSearchParameterMap, FhirContext theFhirContext, Integer theMaxResultsToFetch);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
package ca.uhn.fhir.jpa.search.lastn;
|
|
||||||
|
|
||||||
public class IndexConstants {
|
|
||||||
|
|
||||||
// TODO: These should all be moved into ElasticSearchSvcImpl.
|
|
||||||
public static final String OBSERVATION_INDEX = "observation_index";
|
|
||||||
public static final String CODE_INDEX = "code_index";
|
|
||||||
public static final String OBSERVATION_DOCUMENT_TYPE = "ca.uhn.fhir.jpa.dao.lastn.entity.ObservationIndexedSearchParamLastNEntity";
|
|
||||||
public static final String CODE_DOCUMENT_TYPE = "ca.uhn.fhir.jpa.dao.lastn.entity.ObservationIndexedCodeCodeableConceptEntity";
|
|
||||||
|
|
||||||
public static final String SUBJECT_SEARCH_PARAM = "subject";
|
|
||||||
public static final String PATIENT_SEARCH_PARAM = "patient";
|
|
||||||
public static final String CODE_SEARCH_PARAM = "code";
|
|
||||||
public static final String CATEGORY_SEARCH_PARAM = "category";
|
|
||||||
|
|
||||||
}
|
|
|
@ -104,12 +104,12 @@ public class TestR4Config extends BaseJavaConfigR4 {
|
||||||
retVal.setDriver(new org.h2.Driver());
|
retVal.setDriver(new org.h2.Driver());
|
||||||
// retVal.setDriver(new org.postgresql.Driver());
|
// retVal.setDriver(new org.postgresql.Driver());
|
||||||
retVal.setUrl("jdbc:h2:mem:testdb_r4");
|
retVal.setUrl("jdbc:h2:mem:testdb_r4");
|
||||||
// retVal.setUrl("jdbc:postgresql://localhost:5432/hapi");
|
// retVal.setUrl("jdbc:postgresql://localhost:5432/cdr");
|
||||||
retVal.setMaxWaitMillis(10000);
|
retVal.setMaxWaitMillis(10000);
|
||||||
retVal.setUsername("");
|
retVal.setUsername("");
|
||||||
// retVal.setUsername("hapi");
|
// retVal.setUsername("cdr");
|
||||||
retVal.setPassword("");
|
retVal.setPassword("");
|
||||||
// retVal.setPassword("HapiFHIR");
|
// retVal.setPassword("SmileCDR");
|
||||||
retVal.setMaxTotal(ourMaxThreads);
|
retVal.setMaxTotal(ourMaxThreads);
|
||||||
|
|
||||||
SLF4JLogLevel level = SLF4JLogLevel.INFO;
|
SLF4JLogLevel level = SLF4JLogLevel.INFO;
|
||||||
|
|
|
@ -60,6 +60,9 @@ public class PersistObservationIndexedSearchParamLastNR4IT {
|
||||||
@Autowired
|
@Autowired
|
||||||
ObservationLastNIndexPersistSvc testObservationPersist;
|
ObservationLastNIndexPersistSvc testObservationPersist;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected FhirContext myFhirCtx;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void before() {
|
public void before() {
|
||||||
|
|
||||||
|
@ -106,8 +109,9 @@ public class PersistObservationIndexedSearchParamLastNR4IT {
|
||||||
searchParameterMap.add(Observation.SP_CATEGORY, new TokenAndListParam().addAnd(new TokenOrListParam().addOr(categoryParam)));
|
searchParameterMap.add(Observation.SP_CATEGORY, new TokenAndListParam().addAnd(new TokenOrListParam().addOr(categoryParam)));
|
||||||
TokenParam codeParam = new TokenParam(CODEFIRSTCODINGSYSTEM, CODEFIRSTCODINGCODE);
|
TokenParam codeParam = new TokenParam(CODEFIRSTCODINGSYSTEM, CODEFIRSTCODINGCODE);
|
||||||
searchParameterMap.add(Observation.SP_CODE, new TokenAndListParam().addAnd(new TokenOrListParam().addOr(codeParam)));
|
searchParameterMap.add(Observation.SP_CODE, new TokenAndListParam().addAnd(new TokenOrListParam().addOr(codeParam)));
|
||||||
|
searchParameterMap.setLastNMax(3);
|
||||||
|
|
||||||
List<String> observationIdsOnly = elasticsearchSvc.executeLastN(searchParameterMap, 3, 100);
|
List<String> observationIdsOnly = elasticsearchSvc.executeLastN(searchParameterMap, myFhirCtx, 100);
|
||||||
|
|
||||||
assertEquals(1, observationIdsOnly.size());
|
assertEquals(1, observationIdsOnly.size());
|
||||||
assertEquals(SINGLE_OBSERVATION_PID, observationIdsOnly.get(0));
|
assertEquals(SINGLE_OBSERVATION_PID, observationIdsOnly.get(0));
|
||||||
|
@ -180,15 +184,18 @@ public class PersistObservationIndexedSearchParamLastNR4IT {
|
||||||
// Check that all observations were indexed.
|
// Check that all observations were indexed.
|
||||||
SearchParameterMap searchParameterMap = new SearchParameterMap();
|
SearchParameterMap searchParameterMap = new SearchParameterMap();
|
||||||
searchParameterMap.add(Observation.SP_SUBJECT, multiSubjectParams);
|
searchParameterMap.add(Observation.SP_SUBJECT, multiSubjectParams);
|
||||||
//searchParameterMap.
|
|
||||||
List<String> observationIdsOnly = elasticsearchSvc.executeLastN(searchParameterMap, 10, 200);
|
searchParameterMap.setLastNMax(10);
|
||||||
|
|
||||||
|
List<String> observationIdsOnly = elasticsearchSvc.executeLastN(searchParameterMap, myFhirCtx, 200);
|
||||||
assertEquals(100, observationIdsOnly.size());
|
assertEquals(100, observationIdsOnly.size());
|
||||||
|
|
||||||
// Filter the results by category code.
|
// Filter the results by category code.
|
||||||
TokenParam categoryParam = new TokenParam(CATEGORYFIRSTCODINGSYSTEM, FIRSTCATEGORYFIRSTCODINGCODE);
|
TokenParam categoryParam = new TokenParam(CATEGORYFIRSTCODINGSYSTEM, FIRSTCATEGORYFIRSTCODINGCODE);
|
||||||
searchParameterMap.add(Observation.SP_CATEGORY, new TokenAndListParam().addAnd(new TokenOrListParam().addOr(categoryParam)));
|
searchParameterMap.add(Observation.SP_CATEGORY, new TokenAndListParam().addAnd(new TokenOrListParam().addOr(categoryParam)));
|
||||||
|
|
||||||
observationIdsOnly = elasticsearchSvc.executeLastN(searchParameterMap, 10, 100);
|
|
||||||
|
observationIdsOnly = elasticsearchSvc.executeLastN(searchParameterMap, myFhirCtx, 100);
|
||||||
|
|
||||||
assertEquals(50, observationIdsOnly.size());
|
assertEquals(50, observationIdsOnly.size());
|
||||||
|
|
||||||
|
@ -277,7 +284,8 @@ public class PersistObservationIndexedSearchParamLastNR4IT {
|
||||||
|
|
||||||
SearchParameterMap searchParameterMap = new SearchParameterMap();
|
SearchParameterMap searchParameterMap = new SearchParameterMap();
|
||||||
searchParameterMap.add(Observation.SP_SUBJECT, multiSubjectParams);
|
searchParameterMap.add(Observation.SP_SUBJECT, multiSubjectParams);
|
||||||
List<String> observationIdsOnly = elasticsearchSvc.executeLastN(searchParameterMap, 10, 200);
|
searchParameterMap.setLastNMax(10);
|
||||||
|
List<String> observationIdsOnly = elasticsearchSvc.executeLastN(searchParameterMap, myFhirCtx, 200);
|
||||||
assertEquals(100, observationIdsOnly.size());
|
assertEquals(100, observationIdsOnly.size());
|
||||||
assertTrue(observationIdsOnly.contains("55"));
|
assertTrue(observationIdsOnly.contains("55"));
|
||||||
|
|
||||||
|
@ -295,7 +303,7 @@ public class PersistObservationIndexedSearchParamLastNR4IT {
|
||||||
observation = myResourceIndexedObservationLastNDao.findForIdentifier("55");
|
observation = myResourceIndexedObservationLastNDao.findForIdentifier("55");
|
||||||
assertNull(observation);
|
assertNull(observation);
|
||||||
|
|
||||||
observationIdsOnly = elasticsearchSvc.executeLastN(searchParameterMap, 10, 200);
|
observationIdsOnly = elasticsearchSvc.executeLastN(searchParameterMap, myFhirCtx, 200);
|
||||||
assertEquals(99, observationIdsOnly.size());
|
assertEquals(99, observationIdsOnly.size());
|
||||||
assertTrue(!observationIdsOnly.contains("55"));
|
assertTrue(!observationIdsOnly.contains("55"));
|
||||||
|
|
||||||
|
@ -316,7 +324,9 @@ public class PersistObservationIndexedSearchParamLastNR4IT {
|
||||||
searchParameterMap.add(Observation.SP_CATEGORY, new TokenAndListParam().addAnd(new TokenOrListParam().addOr(categoryParam)));
|
searchParameterMap.add(Observation.SP_CATEGORY, new TokenAndListParam().addAnd(new TokenOrListParam().addOr(categoryParam)));
|
||||||
TokenParam codeParam = new TokenParam(CODEFIRSTCODINGSYSTEM, CODEFIRSTCODINGCODE);
|
TokenParam codeParam = new TokenParam(CODEFIRSTCODINGSYSTEM, CODEFIRSTCODINGCODE);
|
||||||
searchParameterMap.add(Observation.SP_CODE, new TokenAndListParam().addAnd(new TokenOrListParam().addOr(codeParam)));
|
searchParameterMap.add(Observation.SP_CODE, new TokenAndListParam().addAnd(new TokenOrListParam().addOr(codeParam)));
|
||||||
List<String> observationIdsOnly = elasticsearchSvc.executeLastN(searchParameterMap, 10, 200);
|
searchParameterMap.setLastNMax(10);
|
||||||
|
|
||||||
|
List<String> observationIdsOnly = elasticsearchSvc.executeLastN(searchParameterMap, myFhirCtx, 200);
|
||||||
assertEquals(1, observationIdsOnly.size());
|
assertEquals(1, observationIdsOnly.size());
|
||||||
assertTrue(observationIdsOnly.contains(SINGLE_OBSERVATION_PID));
|
assertTrue(observationIdsOnly.contains(SINGLE_OBSERVATION_PID));
|
||||||
|
|
||||||
|
@ -339,7 +349,7 @@ public class PersistObservationIndexedSearchParamLastNR4IT {
|
||||||
assertEquals(newEffectiveDtm.getValue(), updatedObservationEntity.getEffectiveDtm());
|
assertEquals(newEffectiveDtm.getValue(), updatedObservationEntity.getEffectiveDtm());
|
||||||
|
|
||||||
// Repeat earlier Elasticsearch query. This time, should return no matches.
|
// Repeat earlier Elasticsearch query. This time, should return no matches.
|
||||||
observationIdsOnly = elasticsearchSvc.executeLastN(searchParameterMap, 10, 200);
|
observationIdsOnly = elasticsearchSvc.executeLastN(searchParameterMap, myFhirCtx, 200);
|
||||||
assertEquals(0, observationIdsOnly.size());
|
assertEquals(0, observationIdsOnly.size());
|
||||||
|
|
||||||
// Try again with the new patient ID.
|
// Try again with the new patient ID.
|
||||||
|
@ -348,7 +358,8 @@ public class PersistObservationIndexedSearchParamLastNR4IT {
|
||||||
searchParameterMap.add(Observation.SP_SUBJECT, new ReferenceAndListParam().addAnd(new ReferenceOrListParam().addOr(subjectParam)));
|
searchParameterMap.add(Observation.SP_SUBJECT, new ReferenceAndListParam().addAnd(new ReferenceOrListParam().addOr(subjectParam)));
|
||||||
searchParameterMap.add(Observation.SP_CATEGORY, new TokenAndListParam().addAnd(new TokenOrListParam().addOr(categoryParam)));
|
searchParameterMap.add(Observation.SP_CATEGORY, new TokenAndListParam().addAnd(new TokenOrListParam().addOr(categoryParam)));
|
||||||
searchParameterMap.add(Observation.SP_CODE, new TokenAndListParam().addAnd(new TokenOrListParam().addOr(codeParam)));
|
searchParameterMap.add(Observation.SP_CODE, new TokenAndListParam().addAnd(new TokenOrListParam().addOr(codeParam)));
|
||||||
observationIdsOnly = elasticsearchSvc.executeLastN(searchParameterMap, 10, 200);
|
searchParameterMap.setLastNMax(10);
|
||||||
|
observationIdsOnly = elasticsearchSvc.executeLastN(searchParameterMap, myFhirCtx, 200);
|
||||||
|
|
||||||
// Should see the observation returned now.
|
// Should see the observation returned now.
|
||||||
assertEquals(1, observationIdsOnly.size());
|
assertEquals(1, observationIdsOnly.size());
|
||||||
|
@ -398,11 +409,13 @@ public class PersistObservationIndexedSearchParamLastNR4IT {
|
||||||
SearchParameterMap searchParameterMap = new SearchParameterMap();
|
SearchParameterMap searchParameterMap = new SearchParameterMap();
|
||||||
|
|
||||||
// execute Observation ID search - Composite Aggregation
|
// execute Observation ID search - Composite Aggregation
|
||||||
List<String> observationIdsOnly = elasticsearchSvc.executeLastN(searchParameterMap,1, 200);
|
searchParameterMap.setLastNMax(1);
|
||||||
|
List<String> observationIdsOnly = elasticsearchSvc.executeLastN(searchParameterMap,myFhirCtx, 200);
|
||||||
|
|
||||||
assertEquals(20, observationIdsOnly.size());
|
assertEquals(20, observationIdsOnly.size());
|
||||||
|
|
||||||
observationIdsOnly = elasticsearchSvc.executeLastN(searchParameterMap, 3, 200);
|
searchParameterMap.setLastNMax(3);
|
||||||
|
observationIdsOnly = elasticsearchSvc.executeLastN(searchParameterMap, myFhirCtx, 200);
|
||||||
|
|
||||||
assertEquals(38, observationIdsOnly.size());
|
assertEquals(38, observationIdsOnly.size());
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package ca.uhn.fhir.jpa.search.lastn;
|
package ca.uhn.fhir.jpa.search.lastn;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
import ca.uhn.fhir.rest.param.*;
|
import ca.uhn.fhir.rest.param.*;
|
||||||
import ca.uhn.fhir.jpa.search.lastn.config.TestElasticsearchConfig;
|
import ca.uhn.fhir.jpa.search.lastn.config.TestElasticsearchConfig;
|
||||||
|
@ -21,7 +22,6 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static ca.uhn.fhir.jpa.search.lastn.IndexConstants.*;
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@ -35,6 +35,8 @@ public class LastNElasticsearchSvcMultipleObservationsIT {
|
||||||
|
|
||||||
private final Map<String, Map<String, List<Date>>> createdPatientObservationMap = new HashMap<>();
|
private final Map<String, Map<String, List<Date>>> createdPatientObservationMap = new HashMap<>();
|
||||||
|
|
||||||
|
private FhirContext myFhirContext = FhirContext.forR4();
|
||||||
|
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeClass() {
|
public static void beforeClass() {
|
||||||
|
@ -51,8 +53,8 @@ public class LastNElasticsearchSvcMultipleObservationsIT {
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void after() throws IOException {
|
public void after() throws IOException {
|
||||||
elasticsearchSvc.deleteAllDocuments(OBSERVATION_INDEX);
|
elasticsearchSvc.deleteAllDocuments(ElasticsearchSvcImpl.OBSERVATION_INDEX);
|
||||||
elasticsearchSvc.deleteAllDocuments(CODE_INDEX);
|
elasticsearchSvc.deleteAllDocuments(ElasticsearchSvcImpl.CODE_INDEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -80,8 +82,9 @@ public class LastNElasticsearchSvcMultipleObservationsIT {
|
||||||
searchParameterMap.add(Observation.SP_SUBJECT, buildReferenceAndListParam(subjectParam));
|
searchParameterMap.add(Observation.SP_SUBJECT, buildReferenceAndListParam(subjectParam));
|
||||||
subjectParam = new ReferenceParam("Patient", "", "9");
|
subjectParam = new ReferenceParam("Patient", "", "9");
|
||||||
searchParameterMap.add(Observation.SP_SUBJECT, buildReferenceAndListParam(subjectParam));
|
searchParameterMap.add(Observation.SP_SUBJECT, buildReferenceAndListParam(subjectParam));
|
||||||
|
searchParameterMap.setLastNMax(3);
|
||||||
|
|
||||||
List<ObservationJson> observations = elasticsearchSvc.executeLastNWithAllFields(searchParameterMap, 3, 100);
|
List<ObservationJson> observations = elasticsearchSvc.executeLastNWithAllFields(searchParameterMap, myFhirContext);
|
||||||
|
|
||||||
assertEquals(60, observations.size());
|
assertEquals(60, observations.size());
|
||||||
|
|
||||||
|
@ -152,8 +155,9 @@ public class LastNElasticsearchSvcMultipleObservationsIT {
|
||||||
TokenParam codeParam1 = new TokenParam("http://mycodes.org/fhir/observation-code", "test-code-1");
|
TokenParam codeParam1 = new TokenParam("http://mycodes.org/fhir/observation-code", "test-code-1");
|
||||||
TokenParam codeParam2 = new TokenParam("http://mycodes.org/fhir/observation-code", "test-code-2");
|
TokenParam codeParam2 = new TokenParam("http://mycodes.org/fhir/observation-code", "test-code-2");
|
||||||
searchParameterMap.add(Observation.SP_CODE, buildTokenAndListParam(codeParam1, codeParam2));
|
searchParameterMap.add(Observation.SP_CODE, buildTokenAndListParam(codeParam1, codeParam2));
|
||||||
|
searchParameterMap.setLastNMax(100);
|
||||||
|
|
||||||
List<String> observations = elasticsearchSvc.executeLastN(searchParameterMap, 100, 100);
|
List<String> observations = elasticsearchSvc.executeLastN(searchParameterMap, myFhirContext, 100);
|
||||||
|
|
||||||
assertEquals(20, observations.size());
|
assertEquals(20, observations.size());
|
||||||
|
|
||||||
|
@ -164,8 +168,9 @@ public class LastNElasticsearchSvcMultipleObservationsIT {
|
||||||
searchParameterMap.add(Observation.SP_PATIENT, buildReferenceAndListParam(patientParam1, patientParam2));
|
searchParameterMap.add(Observation.SP_PATIENT, buildReferenceAndListParam(patientParam1, patientParam2));
|
||||||
searchParameterMap.add(Observation.SP_CATEGORY, buildTokenAndListParam(categoryParam1, categoryParam2));
|
searchParameterMap.add(Observation.SP_CATEGORY, buildTokenAndListParam(categoryParam1, categoryParam2));
|
||||||
searchParameterMap.add(Observation.SP_CODE, buildTokenAndListParam(codeParam1, codeParam2));
|
searchParameterMap.add(Observation.SP_CODE, buildTokenAndListParam(codeParam1, codeParam2));
|
||||||
|
searchParameterMap.setLastNMax(100);
|
||||||
|
|
||||||
observations = elasticsearchSvc.executeLastN(searchParameterMap, 100, 100);
|
observations = elasticsearchSvc.executeLastN(searchParameterMap, myFhirContext, 100);
|
||||||
|
|
||||||
assertEquals(20, observations.size());
|
assertEquals(20, observations.size());
|
||||||
|
|
||||||
|
@ -197,8 +202,9 @@ public class LastNElasticsearchSvcMultipleObservationsIT {
|
||||||
searchParameterMap.add(Observation.SP_CATEGORY, buildTokenAndListParam(categoryParam));
|
searchParameterMap.add(Observation.SP_CATEGORY, buildTokenAndListParam(categoryParam));
|
||||||
TokenParam codeParam = new TokenParam("test-code-1");
|
TokenParam codeParam = new TokenParam("test-code-1");
|
||||||
searchParameterMap.add(Observation.SP_CODE, buildTokenAndListParam(codeParam));
|
searchParameterMap.add(Observation.SP_CODE, buildTokenAndListParam(codeParam));
|
||||||
|
searchParameterMap.setLastNMax(100);
|
||||||
|
|
||||||
List<String> observations = elasticsearchSvc.executeLastN(searchParameterMap, 100, 100);
|
List<String> observations = elasticsearchSvc.executeLastN(searchParameterMap, myFhirContext, 100);
|
||||||
|
|
||||||
assertEquals(5, observations.size());
|
assertEquals(5, observations.size());
|
||||||
|
|
||||||
|
@ -214,8 +220,9 @@ public class LastNElasticsearchSvcMultipleObservationsIT {
|
||||||
searchParameterMap.add(Observation.SP_CATEGORY, buildTokenAndListParam(categoryParam));
|
searchParameterMap.add(Observation.SP_CATEGORY, buildTokenAndListParam(categoryParam));
|
||||||
TokenParam codeParam = new TokenParam("http://mycodes.org/fhir/observation-code", null);
|
TokenParam codeParam = new TokenParam("http://mycodes.org/fhir/observation-code", null);
|
||||||
searchParameterMap.add(Observation.SP_CODE, buildTokenAndListParam(codeParam));
|
searchParameterMap.add(Observation.SP_CODE, buildTokenAndListParam(codeParam));
|
||||||
|
searchParameterMap.setLastNMax(100);
|
||||||
|
|
||||||
List<String> observations = elasticsearchSvc.executeLastN(searchParameterMap, 100, 100);
|
List<String> observations = elasticsearchSvc.executeLastN(searchParameterMap, myFhirContext, 100);
|
||||||
|
|
||||||
assertEquals(10, observations.size());
|
assertEquals(10, observations.size());
|
||||||
}
|
}
|
||||||
|
@ -231,8 +238,9 @@ public class LastNElasticsearchSvcMultipleObservationsIT {
|
||||||
TokenParam codeParam = new TokenParam("test-code-1 display");
|
TokenParam codeParam = new TokenParam("test-code-1 display");
|
||||||
codeParam.setModifier(TokenParamModifier.TEXT);
|
codeParam.setModifier(TokenParamModifier.TEXT);
|
||||||
searchParameterMap.add(Observation.SP_CODE, buildTokenAndListParam(codeParam));
|
searchParameterMap.add(Observation.SP_CODE, buildTokenAndListParam(codeParam));
|
||||||
|
searchParameterMap.setLastNMax(100);
|
||||||
|
|
||||||
List<String> observations = elasticsearchSvc.executeLastN(searchParameterMap, 100, 100);
|
List<String> observations = elasticsearchSvc.executeLastN(searchParameterMap, myFhirContext, 100);
|
||||||
|
|
||||||
assertEquals(5, observations.size());
|
assertEquals(5, observations.size());
|
||||||
|
|
||||||
|
@ -248,7 +256,9 @@ public class LastNElasticsearchSvcMultipleObservationsIT {
|
||||||
searchParameterMap.add(Observation.SP_CATEGORY, buildTokenAndListParam(categoryParam));
|
searchParameterMap.add(Observation.SP_CATEGORY, buildTokenAndListParam(categoryParam));
|
||||||
TokenParam codeParam = new TokenParam("http://mycodes.org/fhir/observation-code", "test-code-1");
|
TokenParam codeParam = new TokenParam("http://mycodes.org/fhir/observation-code", "test-code-1");
|
||||||
searchParameterMap.add(Observation.SP_CODE, buildTokenAndListParam(codeParam));
|
searchParameterMap.add(Observation.SP_CODE, buildTokenAndListParam(codeParam));
|
||||||
List<String> observations = elasticsearchSvc.executeLastN(searchParameterMap, 100, 100);
|
searchParameterMap.setLastNMax(100);
|
||||||
|
|
||||||
|
List<String> observations = elasticsearchSvc.executeLastN(searchParameterMap, myFhirContext, 100);
|
||||||
assertEquals(0, observations.size());
|
assertEquals(0, observations.size());
|
||||||
|
|
||||||
// Invalid subject
|
// Invalid subject
|
||||||
|
@ -259,7 +269,9 @@ public class LastNElasticsearchSvcMultipleObservationsIT {
|
||||||
searchParameterMap.add(Observation.SP_CATEGORY, buildTokenAndListParam(categoryParam));
|
searchParameterMap.add(Observation.SP_CATEGORY, buildTokenAndListParam(categoryParam));
|
||||||
codeParam = new TokenParam("http://mycodes.org/fhir/observation-code", "test-code-1");
|
codeParam = new TokenParam("http://mycodes.org/fhir/observation-code", "test-code-1");
|
||||||
searchParameterMap.add(Observation.SP_CODE, buildTokenAndListParam(codeParam));
|
searchParameterMap.add(Observation.SP_CODE, buildTokenAndListParam(codeParam));
|
||||||
observations = elasticsearchSvc.executeLastN(searchParameterMap, 100, 100);
|
searchParameterMap.setLastNMax(100);
|
||||||
|
|
||||||
|
observations = elasticsearchSvc.executeLastN(searchParameterMap, myFhirContext, 100);
|
||||||
assertEquals(0, observations.size());
|
assertEquals(0, observations.size());
|
||||||
|
|
||||||
// Invalid observation code
|
// Invalid observation code
|
||||||
|
@ -270,7 +282,9 @@ public class LastNElasticsearchSvcMultipleObservationsIT {
|
||||||
searchParameterMap.add(Observation.SP_CATEGORY, buildTokenAndListParam(categoryParam));
|
searchParameterMap.add(Observation.SP_CATEGORY, buildTokenAndListParam(categoryParam));
|
||||||
codeParam = new TokenParam("http://mycodes.org/fhir/observation-code", "test-code-999");
|
codeParam = new TokenParam("http://mycodes.org/fhir/observation-code", "test-code-999");
|
||||||
searchParameterMap.add(Observation.SP_CODE, buildTokenAndListParam(codeParam));
|
searchParameterMap.add(Observation.SP_CODE, buildTokenAndListParam(codeParam));
|
||||||
observations = elasticsearchSvc.executeLastN(searchParameterMap, 100, 100);
|
searchParameterMap.setLastNMax(100);
|
||||||
|
|
||||||
|
observations = elasticsearchSvc.executeLastN(searchParameterMap, myFhirContext, 100);
|
||||||
assertEquals(0, observations.size());
|
assertEquals(0, observations.size());
|
||||||
|
|
||||||
// Invalid category code
|
// Invalid category code
|
||||||
|
@ -281,7 +295,9 @@ public class LastNElasticsearchSvcMultipleObservationsIT {
|
||||||
searchParameterMap.add(Observation.SP_CATEGORY, buildTokenAndListParam(categoryParam));
|
searchParameterMap.add(Observation.SP_CATEGORY, buildTokenAndListParam(categoryParam));
|
||||||
codeParam = new TokenParam("http://mycodes.org/fhir/observation-code", "test-code-1");
|
codeParam = new TokenParam("http://mycodes.org/fhir/observation-code", "test-code-1");
|
||||||
searchParameterMap.add(Observation.SP_CODE, buildTokenAndListParam(codeParam));
|
searchParameterMap.add(Observation.SP_CODE, buildTokenAndListParam(codeParam));
|
||||||
observations = elasticsearchSvc.executeLastN(searchParameterMap, 100, 100);
|
searchParameterMap.setLastNMax(100);
|
||||||
|
|
||||||
|
observations = elasticsearchSvc.executeLastN(searchParameterMap, myFhirContext, 100);
|
||||||
assertEquals(0, observations.size());
|
assertEquals(0, observations.size());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -341,12 +357,12 @@ public class LastNElasticsearchSvcMultipleObservationsIT {
|
||||||
observationJson.setCategories(categoryConcepts1);
|
observationJson.setCategories(categoryConcepts1);
|
||||||
observationJson.setCode(codeableConceptField1);
|
observationJson.setCode(codeableConceptField1);
|
||||||
observationJson.setCode_concept_id(codeableConceptId1);
|
observationJson.setCode_concept_id(codeableConceptId1);
|
||||||
assertTrue(elasticsearchSvc.performIndex(CODE_INDEX, codeableConceptId1, codeJson1Document, CODE_DOCUMENT_TYPE));
|
assertTrue(elasticsearchSvc.performIndex(ElasticsearchSvcImpl.CODE_INDEX, codeableConceptId1, codeJson1Document, ElasticsearchSvcImpl.CODE_DOCUMENT_TYPE));
|
||||||
} else {
|
} else {
|
||||||
observationJson.setCategories(categoryConcepts2);
|
observationJson.setCategories(categoryConcepts2);
|
||||||
observationJson.setCode(codeableConceptField2);
|
observationJson.setCode(codeableConceptField2);
|
||||||
observationJson.setCode_concept_id(codeableConceptId2);
|
observationJson.setCode_concept_id(codeableConceptId2);
|
||||||
assertTrue(elasticsearchSvc.performIndex(CODE_INDEX, codeableConceptId2, codeJson2Document, CODE_DOCUMENT_TYPE));
|
assertTrue(elasticsearchSvc.performIndex(ElasticsearchSvcImpl.CODE_INDEX, codeableConceptId2, codeJson2Document, ElasticsearchSvcImpl.CODE_DOCUMENT_TYPE));
|
||||||
}
|
}
|
||||||
|
|
||||||
Calendar observationDate = new GregorianCalendar();
|
Calendar observationDate = new GregorianCalendar();
|
||||||
|
@ -355,7 +371,7 @@ public class LastNElasticsearchSvcMultipleObservationsIT {
|
||||||
observationJson.setEffectiveDtm(effectiveDtm);
|
observationJson.setEffectiveDtm(effectiveDtm);
|
||||||
|
|
||||||
String observationDocument = ourMapperNonPrettyPrint.writeValueAsString(observationJson);
|
String observationDocument = ourMapperNonPrettyPrint.writeValueAsString(observationJson);
|
||||||
assertTrue(elasticsearchSvc.performIndex(OBSERVATION_INDEX, identifier, observationDocument, OBSERVATION_DOCUMENT_TYPE));
|
assertTrue(elasticsearchSvc.performIndex(ElasticsearchSvcImpl.OBSERVATION_INDEX, identifier, observationDocument, ElasticsearchSvcImpl.OBSERVATION_DOCUMENT_TYPE));
|
||||||
|
|
||||||
if (createdPatientObservationMap.containsKey(subject)) {
|
if (createdPatientObservationMap.containsKey(subject)) {
|
||||||
Map<String, List<Date>> observationCodeMap = createdPatientObservationMap.get(subject);
|
Map<String, List<Date>> observationCodeMap = createdPatientObservationMap.get(subject);
|
||||||
|
@ -393,7 +409,8 @@ public class LastNElasticsearchSvcMultipleObservationsIT {
|
||||||
@Test
|
@Test
|
||||||
public void testLastNNoParamsQuery() {
|
public void testLastNNoParamsQuery() {
|
||||||
SearchParameterMap searchParameterMap = new SearchParameterMap();
|
SearchParameterMap searchParameterMap = new SearchParameterMap();
|
||||||
List<ObservationJson> observations = elasticsearchSvc.executeLastNWithAllFields(searchParameterMap, 1, 100);
|
searchParameterMap.setLastNMax(1);
|
||||||
|
List<ObservationJson> observations = elasticsearchSvc.executeLastNWithAllFields(searchParameterMap, myFhirContext);
|
||||||
|
|
||||||
assertEquals(2, observations.size());
|
assertEquals(2, observations.size());
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package ca.uhn.fhir.jpa.search.lastn;
|
package ca.uhn.fhir.jpa.search.lastn;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.jpa.search.lastn.config.TestElasticsearchConfig;
|
import ca.uhn.fhir.jpa.search.lastn.config.TestElasticsearchConfig;
|
||||||
import ca.uhn.fhir.jpa.search.lastn.json.CodeJson;
|
import ca.uhn.fhir.jpa.search.lastn.json.CodeJson;
|
||||||
import ca.uhn.fhir.jpa.search.lastn.json.ObservationJson;
|
import ca.uhn.fhir.jpa.search.lastn.json.ObservationJson;
|
||||||
|
@ -67,12 +68,14 @@ public class LastNElasticsearchSvcSingleObservationIT {
|
||||||
final String CODEFIRSTCODINGSYSTEM = "http://mycodes.org/fhir/observation-code";
|
final String CODEFIRSTCODINGSYSTEM = "http://mycodes.org/fhir/observation-code";
|
||||||
final String CODEFIRSTCODINGCODE = "test-code";
|
final String CODEFIRSTCODINGCODE = "test-code";
|
||||||
final String CODEFIRSTCODINGDISPLAY = "test-code display";
|
final String CODEFIRSTCODINGDISPLAY = "test-code display";
|
||||||
final String CODESECONDCODINGSYSTEM = "http://myalternatecodes.org/fhir/observation-code";
|
// final String CODESECONDCODINGSYSTEM = "http://myalternatecodes.org/fhir/observation-code";
|
||||||
final String CODESECONDCODINGCODE = "test-alt-code";
|
// final String CODESECONDCODINGCODE = "test-alt-code";
|
||||||
final String CODESECONDCODINGDISPLAY = "test-alt-code display";
|
// final String CODESECONDCODINGDISPLAY = "test-alt-code display";
|
||||||
final String CODETHIRDCODINGSYSTEM = "http://mysecondaltcodes.org/fhir/observation-code";
|
// final String CODETHIRDCODINGSYSTEM = "http://mysecondaltcodes.org/fhir/observation-code";
|
||||||
final String CODETHIRDCODINGCODE = "test-second-alt-code";
|
// final String CODETHIRDCODINGCODE = "test-second-alt-code";
|
||||||
final String CODETHIRDCODINGDISPLAY = "test-second-alt-code display";
|
// final String CODETHIRDCODINGDISPLAY = "test-second-alt-code display";
|
||||||
|
|
||||||
|
final FhirContext myFhirContext = FhirContext.forR4();
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void beforeClass() {
|
public static void beforeClass() {
|
||||||
|
@ -85,8 +88,8 @@ public class LastNElasticsearchSvcSingleObservationIT {
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void after() throws IOException {
|
public void after() throws IOException {
|
||||||
elasticsearchSvc.deleteAllDocuments(IndexConstants.OBSERVATION_INDEX);
|
elasticsearchSvc.deleteAllDocuments(ElasticsearchSvcImpl.OBSERVATION_INDEX);
|
||||||
elasticsearchSvc.deleteAllDocuments(IndexConstants.CODE_INDEX);
|
elasticsearchSvc.deleteAllDocuments(ElasticsearchSvcImpl.CODE_INDEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -102,14 +105,16 @@ public class LastNElasticsearchSvcSingleObservationIT {
|
||||||
TokenParam codeParam = new TokenParam(CODEFIRSTCODINGSYSTEM, CODEFIRSTCODINGCODE);
|
TokenParam codeParam = new TokenParam(CODEFIRSTCODINGSYSTEM, CODEFIRSTCODINGCODE);
|
||||||
searchParameterMap.add(Observation.SP_CODE, new TokenAndListParam().addAnd(new TokenOrListParam().addOr(codeParam)));
|
searchParameterMap.add(Observation.SP_CODE, new TokenAndListParam().addAnd(new TokenOrListParam().addOr(codeParam)));
|
||||||
|
|
||||||
|
searchParameterMap.setLastNMax(3);
|
||||||
|
|
||||||
// execute Observation ID search
|
// execute Observation ID search
|
||||||
List<String> observationIdsOnly = elasticsearchSvc.executeLastN(searchParameterMap, 3, 100);
|
List<String> observationIdsOnly = elasticsearchSvc.executeLastN(searchParameterMap, myFhirContext, 100);
|
||||||
|
|
||||||
assertEquals(1, observationIdsOnly.size());
|
assertEquals(1, observationIdsOnly.size());
|
||||||
assertEquals(RESOURCEPID, observationIdsOnly.get(0));
|
assertEquals(RESOURCEPID, observationIdsOnly.get(0));
|
||||||
|
|
||||||
// execute Observation search for all search fields
|
// execute Observation search for all search fields
|
||||||
List<ObservationJson> observations = elasticsearchSvc.executeLastNWithAllFields(searchParameterMap, 3, 100);
|
List<ObservationJson> observations = elasticsearchSvc.executeLastNWithAllFields(searchParameterMap, myFhirContext);
|
||||||
|
|
||||||
validateFullObservationSearch(observations);
|
validateFullObservationSearch(observations);
|
||||||
}
|
}
|
||||||
|
@ -243,7 +248,7 @@ public class LastNElasticsearchSvcSingleObservationIT {
|
||||||
assertEquals(String.valueOf(CodeSystemHash.hashCodeSystem(CODEFIRSTCODINGSYSTEM, CODEFIRSTCODINGCODE)), code_coding_code_system_hash);
|
assertEquals(String.valueOf(CodeSystemHash.hashCodeSystem(CODEFIRSTCODINGSYSTEM, CODEFIRSTCODINGCODE)), code_coding_code_system_hash);
|
||||||
|
|
||||||
// Retrieve all Observation codes
|
// Retrieve all Observation codes
|
||||||
List<CodeJson> codes = elasticsearchSvc.queryAllIndexedObservationCodes(1000);
|
List<CodeJson> codes = elasticsearchSvc.queryAllIndexedObservationCodes();
|
||||||
assertEquals(1, codes.size());
|
assertEquals(1, codes.size());
|
||||||
CodeJson persistedObservationCode = codes.get(0);
|
CodeJson persistedObservationCode = codes.get(0);
|
||||||
|
|
||||||
|
@ -331,11 +336,11 @@ public class LastNElasticsearchSvcSingleObservationIT {
|
||||||
indexedObservation.setCode(codeableConceptField);
|
indexedObservation.setCode(codeableConceptField);
|
||||||
|
|
||||||
String observationDocument = ourMapperNonPrettyPrint.writeValueAsString(indexedObservation);
|
String observationDocument = ourMapperNonPrettyPrint.writeValueAsString(indexedObservation);
|
||||||
assertTrue(elasticsearchSvc.performIndex(IndexConstants.OBSERVATION_INDEX, RESOURCEPID, observationDocument, IndexConstants.OBSERVATION_DOCUMENT_TYPE));
|
assertTrue(elasticsearchSvc.performIndex(ElasticsearchSvcImpl.OBSERVATION_INDEX, RESOURCEPID, observationDocument, ElasticsearchSvcImpl.OBSERVATION_DOCUMENT_TYPE));
|
||||||
|
|
||||||
CodeJson observationCode = new CodeJson(codeableConceptField, OBSERVATIONSINGLECODEID);
|
CodeJson observationCode = new CodeJson(codeableConceptField, OBSERVATIONSINGLECODEID);
|
||||||
String codeDocument = ourMapperNonPrettyPrint.writeValueAsString(observationCode);
|
String codeDocument = ourMapperNonPrettyPrint.writeValueAsString(observationCode);
|
||||||
assertTrue(elasticsearchSvc.performIndex(IndexConstants.CODE_INDEX, OBSERVATIONSINGLECODEID, codeDocument, IndexConstants.CODE_DOCUMENT_TYPE));
|
assertTrue(elasticsearchSvc.performIndex(ElasticsearchSvcImpl.CODE_INDEX, OBSERVATIONSINGLECODEID, codeDocument, ElasticsearchSvcImpl.CODE_DOCUMENT_TYPE));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Thread.sleep(1000L);
|
Thread.sleep(1000L);
|
||||||
|
|
|
@ -35,4 +35,66 @@ public class LastNParameterHelper {
|
||||||
throw new InvalidRequestException("$lastn operation is not implemented for FHIR Version " + theContext.getVersion().getVersion().getFhirVersionString());
|
throw new InvalidRequestException("$lastn operation is not implemented for FHIR Version " + theContext.getVersion().getVersion().getFhirVersionString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getSubjectParamName(FhirContext theContext) {
|
||||||
|
if (theContext.getVersion().getVersion() == FhirVersionEnum.R5) {
|
||||||
|
return org.hl7.fhir.r5.model.Observation.SP_SUBJECT;
|
||||||
|
} else if (theContext.getVersion().getVersion() == FhirVersionEnum.R4) {
|
||||||
|
return org.hl7.fhir.r4.model.Observation.SP_SUBJECT;
|
||||||
|
} else if (theContext.getVersion().getVersion() == FhirVersionEnum.DSTU3) {
|
||||||
|
return org.hl7.fhir.dstu3.model.Observation.SP_SUBJECT;
|
||||||
|
} else {
|
||||||
|
throw new InvalidRequestException("$lastn operation is not implemented for FHIR Version " + theContext.getVersion().getVersion().getFhirVersionString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getPatientParamName(FhirContext theContext) {
|
||||||
|
if (theContext.getVersion().getVersion() == FhirVersionEnum.R5) {
|
||||||
|
return org.hl7.fhir.r5.model.Observation.SP_PATIENT;
|
||||||
|
} else if (theContext.getVersion().getVersion() == FhirVersionEnum.R4) {
|
||||||
|
return org.hl7.fhir.r4.model.Observation.SP_PATIENT;
|
||||||
|
} else if (theContext.getVersion().getVersion() == FhirVersionEnum.DSTU3) {
|
||||||
|
return org.hl7.fhir.dstu3.model.Observation.SP_PATIENT;
|
||||||
|
} else {
|
||||||
|
throw new InvalidRequestException("$lastn operation is not implemented for FHIR Version " + theContext.getVersion().getVersion().getFhirVersionString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getEffectiveParamName(FhirContext theContext) {
|
||||||
|
if (theContext.getVersion().getVersion() == FhirVersionEnum.R5) {
|
||||||
|
return org.hl7.fhir.r5.model.Observation.SP_DATE;
|
||||||
|
} else if (theContext.getVersion().getVersion() == FhirVersionEnum.R4) {
|
||||||
|
return org.hl7.fhir.r4.model.Observation.SP_DATE;
|
||||||
|
} else if (theContext.getVersion().getVersion() == FhirVersionEnum.DSTU3) {
|
||||||
|
return org.hl7.fhir.dstu3.model.Observation.SP_DATE;
|
||||||
|
} else {
|
||||||
|
throw new InvalidRequestException("$lastn operation is not implemented for FHIR Version " + theContext.getVersion().getVersion().getFhirVersionString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getCategoryParamName(FhirContext theContext) {
|
||||||
|
if (theContext.getVersion().getVersion() == FhirVersionEnum.R5) {
|
||||||
|
return org.hl7.fhir.r5.model.Observation.SP_CATEGORY;
|
||||||
|
} else if (theContext.getVersion().getVersion() == FhirVersionEnum.R4) {
|
||||||
|
return org.hl7.fhir.r4.model.Observation.SP_CATEGORY;
|
||||||
|
} else if (theContext.getVersion().getVersion() == FhirVersionEnum.DSTU3) {
|
||||||
|
return org.hl7.fhir.dstu3.model.Observation.SP_CATEGORY;
|
||||||
|
} else {
|
||||||
|
throw new InvalidRequestException("$lastn operation is not implemented for FHIR Version " + theContext.getVersion().getVersion().getFhirVersionString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getCodeParamName(FhirContext theContext) {
|
||||||
|
if (theContext.getVersion().getVersion() == FhirVersionEnum.R5) {
|
||||||
|
return org.hl7.fhir.r5.model.Observation.SP_CODE;
|
||||||
|
} else if (theContext.getVersion().getVersion() == FhirVersionEnum.R4) {
|
||||||
|
return org.hl7.fhir.r4.model.Observation.SP_CODE;
|
||||||
|
} else if (theContext.getVersion().getVersion() == FhirVersionEnum.DSTU3) {
|
||||||
|
return org.hl7.fhir.dstu3.model.Observation.SP_CODE;
|
||||||
|
} else {
|
||||||
|
throw new InvalidRequestException("$lastn operation is not implemented for FHIR Version " + theContext.getVersion().getVersion().getFhirVersionString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue