Add documentation and remove requirement for max parameter (defaulted to 1 now).
This commit is contained in:
parent
30dd858f17
commit
c86e46b196
|
@ -47,6 +47,7 @@ page.server_jpa.search=Search
|
||||||
page.server_jpa.performance=Performance
|
page.server_jpa.performance=Performance
|
||||||
page.server_jpa.upgrading=Upgrade Guide
|
page.server_jpa.upgrading=Upgrade Guide
|
||||||
page.server_jpa.diff=Diff Operation
|
page.server_jpa.diff=Diff Operation
|
||||||
|
page.server_jpa.lastn=LastN Operation
|
||||||
|
|
||||||
section.server_jpa_empi.title=JPA Server: EMPI
|
section.server_jpa_empi.title=JPA Server: EMPI
|
||||||
page.server_jpa_empi.empi=Enterprise Master Patient Index
|
page.server_jpa_empi.empi=Enterprise Master Patient Index
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
# LastN Operation
|
||||||
|
|
||||||
|
HAPI FHIR 5.1.0 introduced preliminary support for the `$lastn` operation described [here](http://hl7.org/fhir/observation-operation-lastn.html).
|
||||||
|
|
||||||
|
This implementation of the `$lastn` operation requires an external Elasticsearch server implementation which is used to implement the indexes required by this operation. The following sections describe the current functionality supported by this operation and the configuration needed to enable this operation.
|
||||||
|
|
||||||
|
# Functional Overview and Parameters
|
||||||
|
|
||||||
|
As described in the [FHIR specification](http://hl7.org/fhir/observation-operation-lastn.html), the `$lastn` can be used to retrieve the most recent or last n=number of observations for one or more subjects. This implementation supports the following search parameters:
|
||||||
|
|
||||||
|
* `subject=` or `patient=`: Identifier(s) of patient(s) to return Observation resources for. If not specified, returns most recent observations for all patients.
|
||||||
|
* `category=`: One or more category code search parameters used to filter Observations.
|
||||||
|
* `Observation.code=`: One or more `Observation.code` search parameters use to filter and group observations. If not specified, returns most recent observations for all `Observation.code` values.
|
||||||
|
* `date=`: Date search parameters used to filter Observations by `Observation.effectiveDtm`.
|
||||||
|
* `max=`: The maximum number of observations to return for each `Observation.code`. If not specified, returns only the most recent observation in each group.
|
||||||
|
|
||||||
|
# Limitations
|
||||||
|
|
||||||
|
Search parameters other than those listed above are currently not supported.
|
||||||
|
|
||||||
|
The grouping of Observation resources by `Observation.code` means that the `$lastn` operation will not work in cases where `Observation.code` has more than one coding.
|
||||||
|
|
||||||
|
# Deployment and Configuration
|
||||||
|
|
||||||
|
The `$lastn` operation is disabled by default. The operation can be enabled by setting the DaoConfig#setLastNEnabled property (see [JavaDoc](/hapi-fhir/apidocs/hapi-fhir-jpaserver-api/ca/uhn/fhir/jpa/api/config/DaoConfig.html#setLastNEnabled(boolean))).
|
||||||
|
|
||||||
|
In addition, the Elasticsearch client service, `ElasticsearchSvcImpl` will need to be instantiated with parameters specifying how to connect to the Elasticsearch server, for e.g.:
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Bean()
|
||||||
|
public ElasticsearchSvcImpl elasticsearchSvc() {
|
||||||
|
String elasticsearchHost = "localhost";
|
||||||
|
String elasticsearchUserId = "elastic";
|
||||||
|
String elasticsearchPassword = "changeme";
|
||||||
|
int elasticsearchPort = 9301;
|
||||||
|
|
||||||
|
return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchPort, elasticsearchUserId, elasticsearchPassword);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [JavaDoc](/hapi-fhir/apidocs/hapi-fhir-jpaserver-base/ca/uhn/fhir/jpa/search/lastn/IElasticsearchSvc.html) for more information regarding the Elasticsearch client service.
|
|
@ -311,9 +311,6 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
throw new InvalidRequestException("LastN operation is not enabled on this service, can not process this request");
|
throw new InvalidRequestException("LastN operation is not enabled on this service, can not process this request");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(myParams.getLastNMax() == null) {
|
|
||||||
throw new InvalidRequestException("Max parameter is required for $lastn operation");
|
|
||||||
}
|
|
||||||
List<String> lastnResourceIds = myIElasticsearchSvc.executeLastN(myParams, myContext, 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));
|
||||||
|
|
|
@ -89,7 +89,9 @@ public class BaseJpaResourceProviderObservationDstu3 extends JpaResourceProvider
|
||||||
if (theSubject != null) {
|
if (theSubject != null) {
|
||||||
paramMap.add(Observation.SP_SUBJECT, theSubject);
|
paramMap.add(Observation.SP_SUBJECT, theSubject);
|
||||||
}
|
}
|
||||||
|
if (theMax != null) {
|
||||||
paramMap.setLastNMax(theMax.getValue());
|
paramMap.setLastNMax(theMax.getValue());
|
||||||
|
}
|
||||||
if (theCount != null) {
|
if (theCount != null) {
|
||||||
paramMap.setCount(theCount.getValue());
|
paramMap.setCount(theCount.getValue());
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,9 @@ public class BaseJpaResourceProviderObservationR4 extends JpaResourceProviderR4<
|
||||||
if (theSubject != null) {
|
if (theSubject != null) {
|
||||||
paramMap.add(Observation.SP_SUBJECT, theSubject);
|
paramMap.add(Observation.SP_SUBJECT, theSubject);
|
||||||
}
|
}
|
||||||
|
if(theMax != null) {
|
||||||
paramMap.setLastNMax(theMax.getValue());
|
paramMap.setLastNMax(theMax.getValue());
|
||||||
|
}
|
||||||
if (theCount != null) {
|
if (theCount != null) {
|
||||||
paramMap.setCount(theCount.getValue());
|
paramMap.setCount(theCount.getValue());
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,9 @@ public class BaseJpaResourceProviderObservationR5 extends JpaResourceProviderR5<
|
||||||
if (theSubject != null) {
|
if (theSubject != null) {
|
||||||
paramMap.add(Observation.SP_SUBJECT, theSubject);
|
paramMap.add(Observation.SP_SUBJECT, theSubject);
|
||||||
}
|
}
|
||||||
|
if (theMax != null) {
|
||||||
paramMap.setLastNMax(theMax.getValue());
|
paramMap.setLastNMax(theMax.getValue());
|
||||||
|
}
|
||||||
if (theCount != null) {
|
if (theCount != null) {
|
||||||
paramMap.setCount(theCount.getValue());
|
paramMap.setCount(theCount.getValue());
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,6 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
|
||||||
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";
|
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) {
|
||||||
myRestHighLevelClient = ElasticsearchRestClientFactory.createElasticsearchHighLevelRestClient(theHostname, thePort, theUsername, thePassword);
|
myRestHighLevelClient = ElasticsearchRestClientFactory.createElasticsearchHighLevelRestClient(theHostname, thePort, theUsername, thePassword);
|
||||||
|
|
||||||
|
@ -175,7 +174,7 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
SearchRequest myLastNRequest = buildObservationsSearchRequest(subject, theSearchParameterMap, theFhirContext,
|
SearchRequest myLastNRequest = buildObservationsSearchRequest(subject, theSearchParameterMap, theFhirContext,
|
||||||
createObservationSubjectAggregationBuilder(theSearchParameterMap.getLastNMax(), topHitsInclude));
|
createObservationSubjectAggregationBuilder(getMaxParameter(theSearchParameterMap), topHitsInclude));
|
||||||
try {
|
try {
|
||||||
SearchResponse lastnResponse = executeSearchRequest(myLastNRequest);
|
SearchResponse lastnResponse = executeSearchRequest(myLastNRequest);
|
||||||
searchResults.addAll(buildObservationList(lastnResponse, setValue, theSearchParameterMap, theFhirContext,
|
searchResults.addAll(buildObservationList(lastnResponse, setValue, theSearchParameterMap, theFhirContext,
|
||||||
|
@ -186,7 +185,7 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SearchRequest myLastNRequest = buildObservationsSearchRequest(theSearchParameterMap, theFhirContext,
|
SearchRequest myLastNRequest = buildObservationsSearchRequest(theSearchParameterMap, theFhirContext,
|
||||||
createObservationCodeAggregationBuilder(theSearchParameterMap.getLastNMax(), topHitsInclude));
|
createObservationCodeAggregationBuilder(getMaxParameter(theSearchParameterMap), topHitsInclude));
|
||||||
try {
|
try {
|
||||||
SearchResponse lastnResponse = executeSearchRequest(myLastNRequest);
|
SearchResponse lastnResponse = executeSearchRequest(myLastNRequest);
|
||||||
searchResults.addAll(buildObservationList(lastnResponse, setValue, theSearchParameterMap, theFhirContext,
|
searchResults.addAll(buildObservationList(lastnResponse, setValue, theSearchParameterMap, theFhirContext,
|
||||||
|
@ -198,6 +197,14 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
|
||||||
return searchResults;
|
return searchResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getMaxParameter(SearchParameterMap theSearchParameterMap) {
|
||||||
|
if (theSearchParameterMap.getLastNMax() == null) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return theSearchParameterMap.getLastNMax();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private List<String> getSubjectReferenceCriteria(String thePatientParamName, String theSubjectParamName, SearchParameterMap theSearchParameterMap) {
|
private List<String> getSubjectReferenceCriteria(String thePatientParamName, String theSubjectParamName, SearchParameterMap theSearchParameterMap) {
|
||||||
List<String> subjectReferenceCriteria = new ArrayList<>();
|
List<String> subjectReferenceCriteria = new ArrayList<>();
|
||||||
|
|
||||||
|
@ -231,7 +238,7 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
|
||||||
return referenceList;
|
return referenceList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompositeAggregationBuilder createObservationSubjectAggregationBuilder(int theMaxNumberObservationsPerCode, String[] theTopHitsInclude) {
|
private CompositeAggregationBuilder createObservationSubjectAggregationBuilder(Integer theMaxNumberObservationsPerCode, String[] theTopHitsInclude) {
|
||||||
CompositeValuesSourceBuilder<?> subjectValuesBuilder = new TermsValuesSourceBuilder("subject").field("subject");
|
CompositeValuesSourceBuilder<?> subjectValuesBuilder = new TermsValuesSourceBuilder("subject").field("subject");
|
||||||
List<CompositeValuesSourceBuilder<?>> compositeAggSubjectSources = new ArrayList<>();
|
List<CompositeValuesSourceBuilder<?>> compositeAggSubjectSources = new ArrayList<>();
|
||||||
compositeAggSubjectSources.add(subjectValuesBuilder);
|
compositeAggSubjectSources.add(subjectValuesBuilder);
|
||||||
|
|
|
@ -12,13 +12,13 @@
|
||||||
"type" : "keyword"
|
"type" : "keyword"
|
||||||
},
|
},
|
||||||
"codingdisplay" : {
|
"codingdisplay" : {
|
||||||
"type" : "text"
|
"type" : "keyword"
|
||||||
},
|
},
|
||||||
"codingsystem" : {
|
"codingsystem" : {
|
||||||
"type" : "keyword"
|
"type" : "keyword"
|
||||||
},
|
},
|
||||||
"text" : {
|
"text" : {
|
||||||
"type" : "text"
|
"type" : "keyword"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -208,7 +208,6 @@ public class BaseR4SearchLastN extends BaseJpaTest {
|
||||||
public void testLastNNoPatients() {
|
public void testLastNNoPatients() {
|
||||||
|
|
||||||
SearchParameterMap params = new SearchParameterMap();
|
SearchParameterMap params = new SearchParameterMap();
|
||||||
params.setLastNMax(1);
|
|
||||||
|
|
||||||
params.setLastN(true);
|
params.setLastN(true);
|
||||||
Map<String, String[]> requestParameters = new HashMap<>();
|
Map<String, String[]> requestParameters = new HashMap<>();
|
||||||
|
|
Loading…
Reference in New Issue