Add close method for Elasticsearch service. Fix the partial code match.

This commit is contained in:
ianmarshall 2020-06-08 15:07:02 -04:00
parent 4982e67a0f
commit 30dd858f17
5 changed files with 88 additions and 18 deletions

View File

@ -412,8 +412,8 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
if (textOnlyList.size() > 0) { if (textOnlyList.size() > 0) {
BoolQueryBuilder myTextBoolQueryBuilder = QueryBuilders.boolQuery(); BoolQueryBuilder myTextBoolQueryBuilder = QueryBuilders.boolQuery();
for (String textOnlyParam : textOnlyList) { for (String textOnlyParam : textOnlyList) {
myTextBoolQueryBuilder.should(QueryBuilders.matchQuery("categoryconceptcodingdisplay", textOnlyParam)); myTextBoolQueryBuilder.should(QueryBuilders.matchPhrasePrefixQuery("categoryconceptcodingdisplay", textOnlyParam));
myTextBoolQueryBuilder.should(QueryBuilders.matchQuery("categoryconcepttext", textOnlyParam)); myTextBoolQueryBuilder.should(QueryBuilders.matchPhrasePrefixQuery("categoryconcepttext", textOnlyParam));
} }
theBoolQueryBuilder.must(myTextBoolQueryBuilder); theBoolQueryBuilder.must(myTextBoolQueryBuilder);
} }
@ -510,8 +510,8 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
if (textOnlyList.size() > 0) { if (textOnlyList.size() > 0) {
BoolQueryBuilder myTextBoolQueryBuilder = QueryBuilders.boolQuery(); BoolQueryBuilder myTextBoolQueryBuilder = QueryBuilders.boolQuery();
for (String textOnlyParam : textOnlyList) { for (String textOnlyParam : textOnlyList) {
myTextBoolQueryBuilder.should(QueryBuilders.matchQuery("codeconceptcodingdisplay", textOnlyParam)); myTextBoolQueryBuilder.should(QueryBuilders.matchPhrasePrefixQuery("codeconceptcodingdisplay", textOnlyParam));
myTextBoolQueryBuilder.should(QueryBuilders.matchQuery("codeconcepttext", textOnlyParam)); myTextBoolQueryBuilder.should(QueryBuilders.matchPhrasePrefixQuery("codeconcepttext", textOnlyParam));
} }
theBoolQueryBuilder.must(myTextBoolQueryBuilder); theBoolQueryBuilder.must(myTextBoolQueryBuilder);
} }
@ -685,6 +685,11 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc {
return (indexResponse.getResult() == DocWriteResponse.Result.CREATED) || (indexResponse.getResult() == DocWriteResponse.Result.UPDATED); return (indexResponse.getResult() == DocWriteResponse.Result.CREATED) || (indexResponse.getResult() == DocWriteResponse.Result.UPDATED);
} }
@Override
public void close() throws IOException {
myRestHighLevelClient.close();
}
private IndexRequest createIndexRequest(String theIndexName, String theDocumentId, String theObservationDocument, String theDocumentType) { private IndexRequest createIndexRequest(String theIndexName, String theDocumentId, String theObservationDocument, String theDocumentType) {
IndexRequest request = new IndexRequest(theIndexName); IndexRequest request = new IndexRequest(theIndexName);
request.id(theDocumentId); request.id(theDocumentId);

View File

@ -25,6 +25,7 @@ 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;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import java.io.IOException;
import java.util.List; import java.util.List;
public interface IElasticsearchSvc { public interface IElasticsearchSvc {
@ -75,4 +76,9 @@ public interface IElasticsearchSvc {
*/ */
void deleteObservationDocument(String theDocumentId); void deleteObservationDocument(String theDocumentId);
/**
* Invoked when shutting down.
*/
void close() throws IOException;
} }

View File

@ -4,6 +4,9 @@ import ca.uhn.fhir.jpa.search.lastn.ElasticsearchSvcImpl;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import javax.annotation.PreDestroy;
import java.io.IOException;
@Configuration @Configuration
public class TestR4ConfigWithElasticsearchClient extends TestR4ConfigWithElasticSearch { public class TestR4ConfigWithElasticsearchClient extends TestR4ConfigWithElasticSearch {
@ -13,4 +16,9 @@ public class TestR4ConfigWithElasticsearchClient extends TestR4ConfigWithElastic
return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchPort, elasticsearchUserId, elasticsearchPassword); return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchPort, elasticsearchUserId, elasticsearchPassword);
} }
@PreDestroy
public void stopEsClient() throws IOException {
myElasticsearchSvc().close();
}
} }

View File

@ -229,13 +229,13 @@ public class LastNElasticsearchSvcMultipleObservationsIT {
public void testLastNCodeCodeTextCategoryTextOnly() { public void testLastNCodeCodeTextCategoryTextOnly() {
SearchParameterMap searchParameterMap = new SearchParameterMap(); SearchParameterMap searchParameterMap = new SearchParameterMap();
ReferenceParam subjectParam = new ReferenceParam("Patient", "", "3"); ReferenceParam subjectParam = new ReferenceParam("Patient", "", "3");
// Check case match
searchParameterMap.add(Observation.SP_SUBJECT, buildReferenceAndListParam(subjectParam)); searchParameterMap.add(Observation.SP_SUBJECT, buildReferenceAndListParam(subjectParam));
// Check partial text TokenParam categoryParam = new TokenParam("Heart");
TokenParam categoryParam = new TokenParam("est-heart-ra");
categoryParam.setModifier(TokenParamModifier.TEXT); categoryParam.setModifier(TokenParamModifier.TEXT);
searchParameterMap.add(Observation.SP_CATEGORY, buildTokenAndListParam(categoryParam)); searchParameterMap.add(Observation.SP_CATEGORY, buildTokenAndListParam(categoryParam));
// Check partial text TokenParam codeParam = new TokenParam("Code1");
TokenParam codeParam = new TokenParam("est-code-on");
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); searchParameterMap.setLastNMax(100);
@ -244,6 +244,51 @@ public class LastNElasticsearchSvcMultipleObservationsIT {
assertEquals(5, observations.size()); assertEquals(5, observations.size());
// Check case not match
searchParameterMap = new SearchParameterMap();
searchParameterMap.add(Observation.SP_SUBJECT, buildReferenceAndListParam(subjectParam));
categoryParam = new TokenParam("heart");
categoryParam.setModifier(TokenParamModifier.TEXT);
searchParameterMap.add(Observation.SP_CATEGORY, buildTokenAndListParam(categoryParam));
codeParam = new TokenParam("code1");
codeParam.setModifier(TokenParamModifier.TEXT);
searchParameterMap.add(Observation.SP_CODE, buildTokenAndListParam(codeParam));
searchParameterMap.setLastNMax(100);
observations = elasticsearchSvc.executeLastN(searchParameterMap, myFhirContext, 100);
assertEquals(5, observations.size());
// Check hyphenated strings
searchParameterMap = new SearchParameterMap();
searchParameterMap.add(Observation.SP_SUBJECT, buildReferenceAndListParam(subjectParam));
categoryParam = new TokenParam("heart-rate");
categoryParam.setModifier(TokenParamModifier.TEXT);
searchParameterMap.add(Observation.SP_CATEGORY, buildTokenAndListParam(categoryParam));
codeParam = new TokenParam("code1");
codeParam.setModifier(TokenParamModifier.TEXT);
searchParameterMap.add(Observation.SP_CODE, buildTokenAndListParam(codeParam));
searchParameterMap.setLastNMax(100);
observations = elasticsearchSvc.executeLastN(searchParameterMap, myFhirContext, 100);
assertEquals(5, observations.size());
// Check partial strings
searchParameterMap = new SearchParameterMap();
searchParameterMap.add(Observation.SP_SUBJECT, buildReferenceAndListParam(subjectParam));
categoryParam = new TokenParam("hear");
categoryParam.setModifier(TokenParamModifier.TEXT);
searchParameterMap.add(Observation.SP_CATEGORY, buildTokenAndListParam(categoryParam));
codeParam = new TokenParam("1-obs");
codeParam.setModifier(TokenParamModifier.TEXT);
searchParameterMap.add(Observation.SP_CODE, buildTokenAndListParam(codeParam));
searchParameterMap.setLastNMax(100);
observations = elasticsearchSvc.executeLastN(searchParameterMap, myFhirContext, 100);
assertEquals(5, observations.size());
} }
@Test @Test
@ -416,30 +461,30 @@ public class LastNElasticsearchSvcMultipleObservationsIT {
CodeJson codeJson1 = new CodeJson(); CodeJson codeJson1 = new CodeJson();
codeJson1.setCodeableConceptText("Test Codeable Concept Field for First Code"); codeJson1.setCodeableConceptText("Test Codeable Concept Field for First Code");
codeJson1.setCodeableConceptId(codeableConceptId1); codeJson1.setCodeableConceptId(codeableConceptId1);
codeJson1.addCoding("http://mycodes.org/fhir/observation-code", "test-code-1", "test-code-one display"); codeJson1.addCoding("http://mycodes.org/fhir/observation-code", "test-code-1", "1-Observation Code1");
String codeableConceptId2 = UUID.randomUUID().toString(); String codeableConceptId2 = UUID.randomUUID().toString();
CodeJson codeJson2 = new CodeJson(); CodeJson codeJson2 = new CodeJson();
codeJson2.setCodeableConceptText("Test Codeable Concept Field for Second Code"); codeJson2.setCodeableConceptText("Test Codeable Concept Field for Second Code");
codeJson2.setCodeableConceptId(codeableConceptId1); codeJson2.setCodeableConceptId(codeableConceptId1);
codeJson2.addCoding("http://mycodes.org/fhir/observation-code", "test-code-2", "test-code-two display"); codeJson2.addCoding("http://mycodes.org/fhir/observation-code", "test-code-2", "2-Observation Code2");
// Create CodeableConcepts for two categories, each with three codings. // Create CodeableConcepts for two categories, each with three codings.
// Create three codings and first category CodeableConcept // Create three codings and first category CodeableConcept
List<CodeJson> categoryConcepts1 = new ArrayList<>(); List<CodeJson> categoryConcepts1 = new ArrayList<>();
CodeJson categoryCodeableConcept1 = new CodeJson(); CodeJson categoryCodeableConcept1 = new CodeJson();
categoryCodeableConcept1.setCodeableConceptText("Test Codeable Concept Field for first category"); categoryCodeableConcept1.setCodeableConceptText("Test Codeable Concept Field for first category");
categoryCodeableConcept1.addCoding("http://mycodes.org/fhir/observation-category", "test-heart-rate", "test-heart-rate display"); categoryCodeableConcept1.addCoding("http://mycodes.org/fhir/observation-category", "test-heart-rate", "Test Heart Rate");
categoryCodeableConcept1.addCoding("http://myalternatecodes.org/fhir/observation-category", "test-alt-heart-rate", "test-alt-heart-rate display"); categoryCodeableConcept1.addCoding("http://myalternatecodes.org/fhir/observation-category", "test-alt-heart-rate", "Test Heartrate");
categoryCodeableConcept1.addCoding("http://mysecondaltcodes.org/fhir/observation-category", "test-2nd-alt-heart-rate", "test-2nd-alt-heart-rate display"); categoryCodeableConcept1.addCoding("http://mysecondaltcodes.org/fhir/observation-category", "test-2nd-alt-heart-rate", "Test Heart-Rate");
categoryConcepts1.add(categoryCodeableConcept1); categoryConcepts1.add(categoryCodeableConcept1);
// Create three codings and second category CodeableConcept // Create three codings and second category CodeableConcept
List<CodeJson> categoryConcepts2 = new ArrayList<>(); List<CodeJson> categoryConcepts2 = new ArrayList<>();
CodeJson categoryCodeableConcept2 = new CodeJson(); CodeJson categoryCodeableConcept2 = new CodeJson();
categoryCodeableConcept2.setCodeableConceptText("Test Codeable Concept Field for second category"); categoryCodeableConcept2.setCodeableConceptText("Test Codeable Concept Field for second category");
categoryCodeableConcept2.addCoding("http://mycodes.org/fhir/observation-category", "test-vital-signs", "test-vital-signs display"); categoryCodeableConcept2.addCoding("http://mycodes.org/fhir/observation-category", "test-vital-signs", "Test Vital Signs");
categoryCodeableConcept2.addCoding("http://myalternatecodes.org/fhir/observation-category", "test-alt-vitals", "test-alt-vitals display"); categoryCodeableConcept2.addCoding("http://myalternatecodes.org/fhir/observation-category", "test-alt-vitals", "Test Vital-Signs");
categoryCodeableConcept2.addCoding("http://mysecondaltcodes.org/fhir/observation-category", "test-2nd-alt-vitals", "test-2nd-alt-vitals display"); categoryCodeableConcept2.addCoding("http://mysecondaltcodes.org/fhir/observation-category", "test-2nd-alt-vitals", "Test Vitals");
categoryConcepts2.add(categoryCodeableConcept2); categoryConcepts2.add(categoryCodeableConcept2);
for (int patientCount = 0; patientCount < 10; patientCount++) { for (int patientCount = 0; patientCount < 10; patientCount++) {

View File

@ -23,14 +23,14 @@ public class TestElasticsearchConfig {
@Bean() @Bean()
public ElasticsearchSvcImpl myElasticsearchSvc() throws IOException { public ElasticsearchSvcImpl myElasticsearchSvc() {
int elasticsearchPort = embeddedElasticSearch().getHttpPort(); int elasticsearchPort = embeddedElasticSearch().getHttpPort();
return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchPort, elasticsearchUserId, elasticsearchPassword); return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchPort, elasticsearchUserId, elasticsearchPassword);
} }
@Bean @Bean
public EmbeddedElastic embeddedElasticSearch() { public EmbeddedElastic embeddedElasticSearch() {
EmbeddedElastic embeddedElastic = null; EmbeddedElastic embeddedElastic;
try { try {
embeddedElastic = EmbeddedElastic.builder() embeddedElastic = EmbeddedElastic.builder()
.withElasticVersion(ELASTIC_VERSION) .withElasticVersion(ELASTIC_VERSION)
@ -47,4 +47,10 @@ public class TestElasticsearchConfig {
return embeddedElastic; return embeddedElastic;
} }
@PreDestroy
public void stop() throws IOException {
myElasticsearchSvc().close();
embeddedElasticSearch().stop();
}
} }