diff --git a/hapi-fhir-elasticsearch-6/pom.xml b/hapi-fhir-elasticsearch-6/pom.xml index c63846bc972..495be468d38 100644 --- a/hapi-fhir-elasticsearch-6/pom.xml +++ b/hapi-fhir-elasticsearch-6/pom.xml @@ -1,183 +1,144 @@ - 4.0.0 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - ca.uhn.hapi.fhir - hapi-fhir-elasticsearch-6 - 1.0-SNAPSHOT + + ca.uhn.hapi.fhir + hapi-fhir + 5.1.0-SNAPSHOT + ../pom.xml + - hapi-fhir-elasticsearch-6 - - http://www.example.com + hapi-fhir-elasticsearch-6 - - UTF-8 - 1.7 - 1.7 - + hapi-fhir-elasticsearch-6 - - - junit - junit - 4.12 - test - - - - org.elasticsearch.client - elasticsearch-rest-high-level-client - 6.5.4 - - - com.fasterxml.jackson.core - jackson-core - - - com.fasterxml.jackson.dataformat - * - - - com.github.spullara.mustache.java - compiler - - - com.tdunning - t-digest - - - commons-codec - commons-codec - - - commons-logging - commons-logging - - - net.bytebuddy - byte-buddy - - - net.sf.jopt-simple - jopt-simple - - - org.apache.httpcomponents - * - - - org.apache.lucene - lucene-analyzers-common - - - org.apache.lucene - lucene-backward-codecs - - - org.apache.lucene - lucene-sandbox - - - org.elasticsearch - jna - - - org.hdrhistogram - HdrHistogram - - - org.yaml - snakeyaml - - - - + + UTF-8 + 1.7 + 1.7 + - - - - - - maven-clean-plugin - 3.1.0 - - - - maven-resources-plugin - 3.0.2 - - - maven-compiler-plugin - 3.8.0 - - - maven-surefire-plugin - 2.22.1 - - - maven-jar-plugin - 3.0.2 - - - maven-install-plugin - 2.5.2 - - - maven-deploy-plugin - 2.8.2 - - - - maven-site-plugin - 3.7.1 - - - maven-project-info-reports-plugin - 3.0.0 - - - - - - maven-shade-plugin - 3.2.1 - - - package - - shade - - - true - shaded6 - - - com.carrotsearch.hppc - com.shadehapi.carrotsearch.hppc - - - org.apache.logging.log4j - org.shadehapi.apache.logging.log4j - - - org.apache.lucene - org.shadehapi.apache.lucene - - - org.elasticsearch - org.shadehapi.elasticsearch - - - org.joda - org.shadehapi.joda - - - - - - - - + + + junit + junit + 4.12 + test + + + + org.elasticsearch.client + elasticsearch-rest-high-level-client + 6.5.4 + + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.dataformat + * + + + com.github.spullara.mustache.java + compiler + + + com.tdunning + t-digest + + + commons-codec + commons-codec + + + commons-logging + commons-logging + + + net.bytebuddy + byte-buddy + + + net.sf.jopt-simple + jopt-simple + + + org.apache.httpcomponents + * + + + org.apache.lucene + lucene-analyzers-common + + + org.apache.lucene + lucene-backward-codecs + + + org.apache.lucene + lucene-sandbox + + + org.elasticsearch + jna + + + org.hdrhistogram + HdrHistogram + + + org.yaml + snakeyaml + + + + + + + + + maven-shade-plugin + 3.2.1 + + + package + + shade + + + true + shaded6 + + + com.carrotsearch.hppc + com.shadehapi.carrotsearch.hppc + + + org.apache.logging.log4j + org.shadehapi.apache.logging.log4j + + + org.apache.lucene + org.shadehapi.apache.lucene + + + org.elasticsearch + org.shadehapi.elasticsearch + + + org.joda + org.shadehapi.joda + + + + + + + + diff --git a/hapi-fhir-jpaserver-base/pom.xml b/hapi-fhir-jpaserver-base/pom.xml index ab11a7d0598..891079525ac 100644 --- a/hapi-fhir-jpaserver-base/pom.xml +++ b/hapi-fhir-jpaserver-base/pom.xml @@ -145,6 +145,13 @@ hapi-fhir-validation-resources-r5 ${project.version} + + ca.uhn.hapi.fhir + hapi-fhir-elasticsearch-6 + ${project.version} + shaded6 + + net.ttddyy @@ -587,18 +594,6 @@ org.jetbrains annotations - - ca.uhn.hapi.fhir - hapi-fhir-elasticsearch-6 - 1.0-SNAPSHOT - shaded6 - - - org.postgresql - postgresql - 42.2.9 - - diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java index f52f3119558..5bc3325d53d 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java @@ -224,7 +224,7 @@ public class SearchBuilder implements ISearchBuilder { for (Map.Entry>> nextParamEntry : myParams.entrySet()) { String nextParamName = nextParamEntry.getKey(); if (myParams.isLastN() && LastNParameterHelper.isLastNParameter(nextParamName, myContext)) { - // Skip parameters for Subject, Patient, Code and Category for LastN + // Skip parameters for Subject, Patient, Code and Category for LastN as these will be filtered by Elasticsearch continue; } List> andOrParams = nextParamEntry.getValue(); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/lastn/ElasticsearchSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/lastn/ElasticsearchSvcImpl.java index 814815e6223..d653a7f580f 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/lastn/ElasticsearchSvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/lastn/ElasticsearchSvcImpl.java @@ -44,6 +44,7 @@ import org.shadehapi.elasticsearch.search.sort.SortOrder; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.TreeSet; import java.util.function.Function; import static org.apache.commons.lang3.StringUtils.isBlank; @@ -134,7 +135,6 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc { if (!createIndex(OBSERVATION_INDEX, observationMapping)) { throw new RuntimeException("Failed to create observation index"); } - } private void createCodeIndexIfMissing() throws IOException { @@ -182,23 +182,6 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc { } - @VisibleForTesting - boolean performIndex(String theIndexName, String theDocumentId, String theIndexDocument, String theDocumentType) throws IOException { - IndexResponse indexResponse = myRestHighLevelClient.index(createIndexRequest(theIndexName, theDocumentId, theIndexDocument, theDocumentType), - RequestOptions.DEFAULT); - - return (indexResponse.getResult() == DocWriteResponse.Result.CREATED) || (indexResponse.getResult() == DocWriteResponse.Result.UPDATED); - } - - private IndexRequest createIndexRequest(String theIndexName, String theDocumentId, String theObservationDocument, String theDocumentType) { - IndexRequest request = new IndexRequest(theIndexName); - request.id(theDocumentId); - request.type(theDocumentType); - - request.source(theObservationDocument, XContentType.JSON); - return request; - } - private boolean indexExists(String theIndexName) throws IOException { GetIndexRequest request = new GetIndexRequest(); request.indices(theIndexName); @@ -209,90 +192,79 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc { public List executeLastN(SearchParameterMap theSearchParameterMap, FhirContext theFhirContext, Integer theMaxResultsToFetch) { String OBSERVATION_IDENTIFIER_FIELD_NAME = "identifier"; String[] topHitsInclude = {OBSERVATION_IDENTIFIER_FIELD_NAME}; - try { - List responses = buildAndExecuteSearch(theSearchParameterMap, theFhirContext, topHitsInclude); - List observationIds = new ArrayList<>(); - for (SearchResponse response : responses) { - Integer maxResultsToAdd = null; - if (theMaxResultsToFetch != null) { - maxResultsToAdd = theMaxResultsToFetch - observationIds.size(); - } - observationIds.addAll(buildObservationList(response, ObservationJson::getIdentifier, theSearchParameterMap, theFhirContext, maxResultsToAdd)); - } - return observationIds; - } catch (IOException theE) { - throw new InvalidRequestException("Unable to execute LastN request", theE); - } + return buildAndExecuteSearch(theSearchParameterMap, theFhirContext, topHitsInclude, + ObservationJson::getIdentifier, theMaxResultsToFetch); } - private List buildAndExecuteSearch(SearchParameterMap theSearchParameterMap, FhirContext theFhirContext, - String[] topHitsInclude) { - List responses = new ArrayList<>(); + private List buildAndExecuteSearch(SearchParameterMap theSearchParameterMap, FhirContext theFhirContext, + String[] topHitsInclude, Function setValue, Integer theMaxResultsToFetch) { String patientParamName = LastNParameterHelper.getPatientParamName(theFhirContext); String subjectParamName = LastNParameterHelper.getSubjectParamName(theFhirContext); + List searchResults = new ArrayList<>(); if (theSearchParameterMap.containsKey(patientParamName) || theSearchParameterMap.containsKey(subjectParamName)) { - ArrayList subjectReferenceCriteria = new ArrayList<>(); - List> patientParams = new ArrayList<>(); - if (theSearchParameterMap.get(patientParamName) != null) { - patientParams.addAll(theSearchParameterMap.get(patientParamName)); - } - if (theSearchParameterMap.get(subjectParamName) != null) { - patientParams.addAll(theSearchParameterMap.get(subjectParamName)); - } - for (List nextSubjectList : patientParams) { - subjectReferenceCriteria.addAll(getReferenceValues(nextSubjectList)); - } - for (String subject : subjectReferenceCriteria) { + for (String subject : getSubjectReferenceCriteria(patientParamName, subjectParamName, theSearchParameterMap)) { + if (theMaxResultsToFetch != null && searchResults.size() >= theMaxResultsToFetch) { + break; + } SearchRequest myLastNRequest = buildObservationsSearchRequest(subject, theSearchParameterMap, theFhirContext, - createCompositeAggregationBuilder(theSearchParameterMap.getLastNMax(), topHitsInclude)); + createObservationSubjectAggregationBuilder(theSearchParameterMap.getLastNMax(), topHitsInclude)); try { SearchResponse lastnResponse = executeSearchRequest(myLastNRequest); - responses.add(lastnResponse); + searchResults.addAll(buildObservationList(lastnResponse, setValue, theSearchParameterMap, theFhirContext, + theMaxResultsToFetch)); } catch (IOException theE) { throw new InvalidRequestException("Unable to execute LastN request", theE); } } } else { - SearchRequest myLastNRequest = buildObservationsSearchRequest(theSearchParameterMap, theFhirContext, createObservationCodeAggregationBuilder(theSearchParameterMap.getLastNMax(), topHitsInclude)); + SearchRequest myLastNRequest = buildObservationsSearchRequest(theSearchParameterMap, theFhirContext, + createObservationCodeAggregationBuilder(theSearchParameterMap.getLastNMax(), topHitsInclude)); try { SearchResponse lastnResponse = executeSearchRequest(myLastNRequest); - responses.add(lastnResponse); + searchResults.addAll(buildObservationList(lastnResponse, setValue, theSearchParameterMap, theFhirContext, + theMaxResultsToFetch)); } catch (IOException theE) { throw new InvalidRequestException("Unable to execute LastN request", theE); } - } - return responses; + return searchResults; } - @VisibleForTesting - List executeLastNWithAllFields(SearchParameterMap theSearchParameterMap, FhirContext theFhirContext) { - try { - List responses = buildAndExecuteSearch(theSearchParameterMap, theFhirContext, null); - List observationDocuments = new ArrayList<>(); - for (SearchResponse response : responses) { - observationDocuments.addAll(buildObservationList(response, t -> t, theSearchParameterMap, theFhirContext, 100)); + private List getSubjectReferenceCriteria(String thePatientParamName, String theSubjectParamName, SearchParameterMap theSearchParameterMap) { + List subjectReferenceCriteria = new ArrayList<>(); + + List> patientParams = new ArrayList<>(); + if (theSearchParameterMap.get(thePatientParamName) != null) { + patientParams.addAll(theSearchParameterMap.get(thePatientParamName)); + } + if (theSearchParameterMap.get(theSubjectParamName) != null) { + patientParams.addAll(theSearchParameterMap.get(theSubjectParamName)); + } + for (List nextSubjectList : patientParams) { + subjectReferenceCriteria.addAll(getReferenceValues(nextSubjectList)); + } + return subjectReferenceCriteria; + } + + private TreeSet getReferenceValues(List referenceParams) { + TreeSet referenceList = new TreeSet<>(); + + for (IQueryParameterType nextOr : referenceParams) { + + if (nextOr instanceof ReferenceParam) { + ReferenceParam ref = (ReferenceParam) nextOr; + if (isBlank(ref.getChain())) { + referenceList.add(ref.getValue()); + } + } else { + throw new IllegalArgumentException("Invalid token type (expecting ReferenceParam): " + nextOr.getClass()); } - return observationDocuments; - } catch (IOException theE) { - throw new InvalidRequestException("Unable to execute LastN request", theE); } + return referenceList; } - @VisibleForTesting - List queryAllIndexedObservationCodes() throws IOException { - SearchRequest codeSearchRequest = new SearchRequest(CODE_INDEX); - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - // Query - searchSourceBuilder.query(QueryBuilders.matchAllQuery()); - searchSourceBuilder.size(1000); - codeSearchRequest.source(searchSourceBuilder); - SearchResponse codeSearchResponse = executeSearchRequest(codeSearchRequest); - return buildCodeResult(codeSearchResponse); - } - - private CompositeAggregationBuilder createCompositeAggregationBuilder(int theMaxNumberObservationsPerCode, String[] theTopHitsInclude) { + private CompositeAggregationBuilder createObservationSubjectAggregationBuilder(int theMaxNumberObservationsPerCode, String[] theTopHitsInclude) { CompositeValuesSourceBuilder subjectValuesBuilder = new TermsValuesSourceBuilder("subject").field("subject"); List> compositeAggSubjectSources = new ArrayList(); compositeAggSubjectSources.add(subjectValuesBuilder); @@ -395,16 +367,6 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc { return parsedTopHits.getHits().getHits(); } - private List buildCodeResult(SearchResponse theSearchResponse) throws JsonProcessingException { - SearchHits codeHits = theSearchResponse.getHits(); - List codes = new ArrayList<>(); - for (SearchHit codeHit : codeHits) { - CodeJson code = objectMapper.readValue(codeHit.getSourceAsString(), CodeJson.class); - codes.add(code); - } - return codes; - } - private SearchRequest buildObservationsSearchRequest(SearchParameterMap theSearchParameterMap, FhirContext theFhirContext, AggregationBuilder theAggregationBuilder) { SearchRequest searchRequest = new SearchRequest(OBSERVATION_INDEX); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); @@ -453,23 +415,6 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc { || theSearchParameterMap.containsKey(LastNParameterHelper.getCodeParamName(theFhirContext))); } - private List getReferenceValues(List referenceParams) { - ArrayList referenceList = new ArrayList<>(); - - for (IQueryParameterType nextOr : referenceParams) { - - if (nextOr instanceof ReferenceParam) { - ReferenceParam ref = (ReferenceParam) nextOr; - if (isBlank(ref.getChain())) { - referenceList.add(ref.getValue()); - } - } else { - throw new IllegalArgumentException("Invalid token type (expecting ReferenceParam): " + nextOr.getClass()); - } - } - return referenceList; - } - private void addCategoriesCriteria(BoolQueryBuilder theBoolQueryBuilder, SearchParameterMap theSearchParameterMap, FhirContext theFhirContext) { String categoryParamName = LastNParameterHelper.getCategoryParamName(theFhirContext); if (theSearchParameterMap.containsKey(categoryParamName)) { @@ -603,6 +548,50 @@ public class ElasticsearchSvcImpl implements IElasticsearchSvc { } + @VisibleForTesting + List executeLastNWithAllFields(SearchParameterMap theSearchParameterMap, FhirContext theFhirContext) { + return buildAndExecuteSearch(theSearchParameterMap, theFhirContext, null, t -> t, 100); + } + + @VisibleForTesting + List queryAllIndexedObservationCodes() throws IOException { + SearchRequest codeSearchRequest = new SearchRequest(CODE_INDEX); + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + // Query + searchSourceBuilder.query(QueryBuilders.matchAllQuery()); + searchSourceBuilder.size(1000); + codeSearchRequest.source(searchSourceBuilder); + SearchResponse codeSearchResponse = executeSearchRequest(codeSearchRequest); + return buildCodeResult(codeSearchResponse); + } + + private List buildCodeResult(SearchResponse theSearchResponse) throws JsonProcessingException { + SearchHits codeHits = theSearchResponse.getHits(); + List codes = new ArrayList<>(); + for (SearchHit codeHit : codeHits) { + CodeJson code = objectMapper.readValue(codeHit.getSourceAsString(), CodeJson.class); + codes.add(code); + } + return codes; + } + + @VisibleForTesting + boolean performIndex(String theIndexName, String theDocumentId, String theIndexDocument, String theDocumentType) throws IOException { + IndexResponse indexResponse = myRestHighLevelClient.index(createIndexRequest(theIndexName, theDocumentId, theIndexDocument, theDocumentType), + RequestOptions.DEFAULT); + + return (indexResponse.getResult() == DocWriteResponse.Result.CREATED) || (indexResponse.getResult() == DocWriteResponse.Result.UPDATED); + } + + private IndexRequest createIndexRequest(String theIndexName, String theDocumentId, String theObservationDocument, String theDocumentType) { + IndexRequest request = new IndexRequest(theIndexName); + request.id(theDocumentId); + request.type(theDocumentType); + + request.source(theObservationDocument, XContentType.JSON); + return request; + } + @VisibleForTesting void deleteAllDocuments(String theIndexName) throws IOException { DeleteByQueryRequest deleteByQueryRequest = new DeleteByQueryRequest(theIndexName); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/TestUtil.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/TestUtil.java index c038fdb1399..1bea0ca4b24 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/TestUtil.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/TestUtil.java @@ -131,13 +131,15 @@ public class TestUtil { OneToOne oneToOne = nextField.getAnnotation(OneToOne.class); boolean isOtherSideOfOneToManyMapping = oneToMany != null && isNotBlank(oneToMany.mappedBy()); boolean isOtherSideOfOneToOneMapping = oneToOne != null && isNotBlank(oneToOne.mappedBy()); + boolean isField = nextField.getAnnotation(org.hibernate.search.annotations.Field.class) != null; Validate.isTrue( hasEmbedded || hasColumn || hasJoinColumn || isOtherSideOfOneToManyMapping || isOtherSideOfOneToOneMapping || - hasEmbeddedId, "Non-transient has no @Column or @JoinColumn or @EmbeddedId: " + nextField); + hasEmbeddedId || + isField, "Non-transient has no @Column or @JoinColumn or @EmbeddedId: " + nextField); } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestR4Config.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestR4Config.java index 48d2a12d247..f479832e04f 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestR4Config.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestR4Config.java @@ -102,22 +102,16 @@ public class TestR4Config extends BaseJavaConfigR4 { }; retVal.setDriver(new org.h2.Driver()); -// retVal.setDriver(new org.postgresql.Driver()); retVal.setUrl("jdbc:h2:mem:testdb_r4"); -// retVal.setUrl("jdbc:postgresql://localhost:5432/cdr"); retVal.setMaxWaitMillis(10000); retVal.setUsername(""); -// retVal.setUsername("cdr"); retVal.setPassword(""); -// retVal.setPassword("SmileCDR"); retVal.setMaxTotal(ourMaxThreads); SLF4JLogLevel level = SLF4JLogLevel.INFO; DataSource dataSource = ProxyDataSourceBuilder .create(retVal) -// .logQueryBySlf4j(level, "SQL") .logSlowQueryBySlf4j(10, TimeUnit.SECONDS) -// .countQuery(new ThreadQueryCountHolder()) .beforeQuery(new BlockLargeNumbersOfParamsListener()) .afterQuery(captureQueriesListener()) .afterQuery(new CurrentThreadCaptureQueriesListener()) @@ -149,7 +143,6 @@ public class TestR4Config extends BaseJavaConfigR4 { extraProperties.put("hibernate.show_sql", "false"); extraProperties.put("hibernate.hbm2ddl.auto", "update"); extraProperties.put("hibernate.dialect", H2Dialect.class.getName()); -// extraProperties.put("hibernate.dialect", org.hibernate.dialect.PostgreSQL95Dialect.class.getName()); extraProperties.put("hibernate.search.model_mapping", ca.uhn.fhir.jpa.search.LuceneSearchMappingFactory.class.getName()); extraProperties.put("hibernate.search.default.directory_provider", "local-heap"); extraProperties.put("hibernate.search.lucene_version", "LUCENE_CURRENT"); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestR4ConfigWithElasticSearch.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestR4ConfigWithElasticSearch.java index 1b90253383d..ebf3fc9e094 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestR4ConfigWithElasticSearch.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestR4ConfigWithElasticSearch.java @@ -24,9 +24,7 @@ public class TestR4ConfigWithElasticSearch extends TestR4Config { private static final String ELASTIC_VERSION = "6.5.4"; protected final String elasticsearchHost = "localhost"; protected final String elasticsearchUserId = ""; -// protected final String elasticsearchUserId = "elastic"; protected final String elasticsearchPassword = ""; -// protected final String elasticsearchPassword = "changeme"; @Override @@ -36,7 +34,6 @@ public class TestR4ConfigWithElasticSearch extends TestR4Config { // Force elasticsearch to start first int httpPort = embeddedElasticSearch().getHttpPort(); -// int httpPort = 9301; ourLog.info("ElasticSearch started on port: {}", httpPort); new ElasticsearchHibernatePropertiesBuilder() diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestR4ConfigWithElasticsearchClient.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestR4ConfigWithElasticsearchClient.java index 607457c8edd..9ff6bc4c491 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestR4ConfigWithElasticsearchClient.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestR4ConfigWithElasticsearchClient.java @@ -10,7 +10,6 @@ public class TestR4ConfigWithElasticsearchClient extends TestR4ConfigWithElastic @Bean() public ElasticsearchSvcImpl myElasticsearchSvc() { int elasticsearchPort = embeddedElasticSearch().getHttpPort(); -// int elasticsearchPort = 9301; return new ElasticsearchSvcImpl(elasticsearchHost, elasticsearchPort, elasticsearchUserId, elasticsearchPassword); } diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ObservationIndexedCodeCodeableConceptEntity.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ObservationIndexedCodeCodeableConceptEntity.java index 4dea98a0002..93d1a916086 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ObservationIndexedCodeCodeableConceptEntity.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ObservationIndexedCodeCodeableConceptEntity.java @@ -10,16 +10,18 @@ import javax.persistence.*; @Entity @Indexed(index = "code_index") @Embeddable -@Table(name = "HFJ_SPIDX_LASTN_CODEABLE_CONCEPT") +@Table(name = "HFJ_SPIDX_LASTN_CODE_CONCEPT") public class ObservationIndexedCodeCodeableConceptEntity { - @Id + public static final int MAX_LENGTH = 200; + + @Id @DocumentId(name = "codeable_concept_id") - @Column(name="CODEABLE_CONCEPT_ID") + @Column(name="CODEABLE_CONCEPT_ID", length = MAX_LENGTH) private String myCodeableConceptId; @Field(name = "text") - @Column(name = "CODEABLE_CONCEPT_TEXT", nullable = true) + @Column(name = "CODEABLE_CONCEPT_TEXT", nullable = true, length = MAX_LENGTH) private String myCodeableConceptText; // TODO: Make coding a Collection. Need to first figure out how to maintain this over time. diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ObservationIndexedCodeCodingEntity.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ObservationIndexedCodeCodingEntity.java index 5722022af75..7373f04bc91 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ObservationIndexedCodeCodingEntity.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ObservationIndexedCodeCodingEntity.java @@ -11,6 +11,8 @@ import javax.persistence.*; @Table(name = "HFJ_SPIDX_LASTN_CODING") public class ObservationIndexedCodeCodingEntity { + public static final int MAX_LENGTH = 200; + // TODO: Fix this to allow multiple codings for observation code // @Id // @SequenceGenerator(name = "SEQ_CODING_FIELD", sequenceName = "SEQ_CODING_FIELD") @@ -18,7 +20,7 @@ public class ObservationIndexedCodeCodingEntity { // private Long myId; @Id - @Column(name="CODEABLE_CONCEPT_ID") + @Column(name="CODEABLE_CONCEPT_ID", length = MAX_LENGTH) private String myCodeableConceptId; @Field (name = "code", analyze = Analyze.NO) diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ObservationIndexedSearchParamLastNEntity.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ObservationIndexedSearchParamLastNEntity.java index 1d0695c1537..b99193b653a 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ObservationIndexedSearchParamLastNEntity.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ObservationIndexedSearchParamLastNEntity.java @@ -13,6 +13,8 @@ import java.util.*; @Indexed(index = "observation_index") public class ObservationIndexedSearchParamLastNEntity { + public static final int MAX_LENGTH = 200; + @Id @SequenceGenerator(name = "SEQ_LASTN", sequenceName = "SEQ_LASTN") @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_LASTN") @@ -20,7 +22,7 @@ public class ObservationIndexedSearchParamLastNEntity { private Long myId; @Field(name = "subject", analyze = Analyze.NO) - @Column(name = "LASTN_SUBJECT_ID", nullable = true) + @Column(name = "LASTN_SUBJECT_ID", nullable = true, length = MAX_LENGTH) private String mySubject; @ManyToOne(fetch = FetchType.LAZY) @@ -29,7 +31,7 @@ public class ObservationIndexedSearchParamLastNEntity { private ObservationIndexedCodeCodeableConceptEntity myObservationCode; @Field(name = "codeconceptid", analyze = Analyze.NO) - @Column(name = "CODEABLE_CONCEPT_ID", nullable = false, updatable = false, insertable = false) + @Column(name = "CODEABLE_CONCEPT_ID", nullable = false, updatable = false, insertable = false, length = MAX_LENGTH) private String myCodeNormalizedId; @IndexedEmbedded(depth = 2, prefix = "categoryconcept") @@ -42,7 +44,7 @@ public class ObservationIndexedSearchParamLastNEntity { private Date myEffectiveDtm; @DocumentId(name = "identifier") - @Column(name = "RESOURCE_IDENTIFIER", nullable = false) + @Column(name = "RESOURCE_IDENTIFIER", nullable = false, length = MAX_LENGTH) private String myIdentifier; public ObservationIndexedSearchParamLastNEntity() { diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/BaseSearchParamExtractor.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/BaseSearchParamExtractor.java index 24cd063e0be..74891a5aa54 100644 --- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/BaseSearchParamExtractor.java +++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/BaseSearchParamExtractor.java @@ -165,12 +165,6 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor return new ResourceLinkExtractor(); } - @Override - public PathAndRef extractReferenceLinkFromResource(IBase theValue, String thePath) { - ResourceLinkExtractor extractor = new ResourceLinkExtractor(); - return extractor.get(theValue, thePath); - } - private class ResourceLinkExtractor implements IExtractor { private PathAndRef myPathAndRef = null; @@ -249,16 +243,10 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor } } - private List extractParamsAsQueryTokens(RuntimeSearchParam theSearchParam, IBaseResource theResource, IExtractor theExtractor) { - SearchParamSet params = new SearchParamSet<>(); - extractSearchParam(theSearchParam, theResource, theExtractor, params); - return toStringList(params); - } - - private List toStringList(SearchParamSet theParams) { - return theParams.stream() - .map(param -> param.toQueryParameterType().getValueAsQueryToken(myContext)) - .collect(Collectors.toList()); + @Override + public PathAndRef extractReferenceLinkFromResource(IBase theValue, String thePath) { + ResourceLinkExtractor extractor = new ResourceLinkExtractor(); + return extractor.get(theValue, thePath); } @Override @@ -309,6 +297,18 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor .collect(Collectors.toList()); } + private List extractParamsAsQueryTokens(RuntimeSearchParam theSearchParam, IBaseResource theResource, IExtractor theExtractor) { + SearchParamSet params = new SearchParamSet<>(); + extractSearchParam(theSearchParam, theResource, theExtractor, params); + return toStringList(params); + } + + private List toStringList(SearchParamSet theParams) { + return theParams.stream() + .map(param -> param.toQueryParameterType().getValueAsQueryToken(myContext)) + .collect(Collectors.toList()); + } + @Override public SearchParamSet extractSearchParamTokens(IBaseResource theResource) { IExtractor extractor = createTokenExtractor(theResource); @@ -734,6 +734,20 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor return tokenTextIndexingEnabledForSearchParam(myModelConfig, theSearchParam); } + private void addToken_CodeableConcept(String theResourceType, Set theParams, RuntimeSearchParam theSearchParam, IBase theValue) { + List codings = getCodingsFromCodeableConcept(theValue); + for (IBase nextCoding : codings) { + addToken_Coding(theResourceType, theParams, theSearchParam, nextCoding); + } + + if (shouldIndexTextComponentOfToken(theSearchParam)) { + String text = getDisplayTextFromCodeableConcept(theValue); + if (isNotBlank(text)) { + createStringIndexIfNotBlank(theResourceType, theParams, theSearchParam, text); + } + } + } + @Override public List getCodingsFromCodeableConcept(IBase theValue) { String nextType = BaseSearchParamExtractor.this.toRootTypeName(theValue); @@ -754,20 +768,6 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor } } - private void addToken_CodeableConcept(String theResourceType, Set theParams, RuntimeSearchParam theSearchParam, IBase theValue) { - List codings = getCodingsFromCodeableConcept(theValue); - for (IBase nextCoding : codings) { - addToken_Coding(theResourceType, theParams, theSearchParam, nextCoding); - } - - if (shouldIndexTextComponentOfToken(theSearchParam)) { - String text = getDisplayTextFromCodeableConcept(theValue); - if (isNotBlank(text)) { - createStringIndexIfNotBlank(theResourceType, theParams, theSearchParam, text); - } - } - } - private void addToken_Coding(String theResourceType, Set theParams, RuntimeSearchParam theSearchParam, IBase theValue) { ResourceIndexedSearchParamToken resourceIndexedSearchParamToken = createSearchParamForCoding(theResourceType, theSearchParam, theValue); if (resourceIndexedSearchParamToken != null) { @@ -822,61 +822,6 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor } } - private void addDate_Period(String theResourceType, Set theParams, RuntimeSearchParam theSearchParam, IBase theValue) { - Date start = extractValueAsDate(myPeriodStartValueChild, theValue); - String startAsString = extractValueAsString(myPeriodStartValueChild, theValue); - Date end = extractValueAsDate(myPeriodEndValueChild, theValue); - String endAsString = extractValueAsString(myPeriodEndValueChild, theValue); - - if (start != null || end != null) { - ResourceIndexedSearchParamDate nextEntity = new ResourceIndexedSearchParamDate(myPartitionSettings, theResourceType, theSearchParam.getName(), start, startAsString, end, endAsString, startAsString); - theParams.add(nextEntity); - } - } - - private void addDate_Timing(String theResourceType, Set theParams, RuntimeSearchParam theSearchParam, IBase theValue) { - List> values = extractValuesAsFhirDates(myTimingEventValueChild, theValue); - - TreeSet dates = new TreeSet<>(); - TreeSet dateStrings = new TreeSet<>(); - String firstValue = null; - String finalValue = null; - for (IPrimitiveType nextEvent : values) { - if (nextEvent.getValue() != null) { - dates.add(nextEvent.getValue()); - if (firstValue == null) { - firstValue = nextEvent.getValueAsString(); - } - finalValue = nextEvent.getValueAsString(); - } - } - - Optional repeat = myTimingRepeatValueChild.getAccessor().getFirstValueOrNull(theValue); - if (repeat.isPresent()) { - Optional bounds = myTimingRepeatBoundsValueChild.getAccessor().getFirstValueOrNull(repeat.get()); - if (bounds.isPresent()) { - String boundsType = toRootTypeName(bounds.get()); - if ("Period".equals(boundsType)) { - Date start = extractValueAsDate(myPeriodStartValueChild, bounds.get()); - Date end = extractValueAsDate(myPeriodEndValueChild, bounds.get()); - String endString = extractValueAsString(myPeriodEndValueChild, bounds.get()); - dates.add(start); - dates.add(end); - //TODO Check if this logic is valid. Does the start of the first period indicate a lower bound?? - if (firstValue == null) { - firstValue = extractValueAsString(myPeriodStartValueChild, bounds.get()); - } - finalValue = endString; - } - } - } - - if (!dates.isEmpty()) { - ResourceIndexedSearchParamDate nextEntity = new ResourceIndexedSearchParamDate(myPartitionSettings, theResourceType, theSearchParam.getName(), dates.first(), firstValue, dates.last(), finalValue, firstValue); - theParams.add(nextEntity); - } - } - private void addNumber_Duration(String theResourceType, Set theParams, RuntimeSearchParam theSearchParam, IBase theValue) { String system = extractValueAsString(myDurationSystemValueChild, theValue); String code = extractValueAsString(myDurationCodeValueChild, theValue); @@ -1060,15 +1005,6 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor return elementDefinition.getName(); } - @SuppressWarnings("unchecked") - private void addDateTimeTypes(String theResourceType, Set theParams, RuntimeSearchParam theSearchParam, IBase theValue) { - IPrimitiveType nextBaseDateTime = (IPrimitiveType) theValue; - if (nextBaseDateTime.getValue() != null) { - ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate(myPartitionSettings, theResourceType, theSearchParam.getName(), nextBaseDateTime.getValue(), nextBaseDateTime.getValueAsString(), nextBaseDateTime.getValue(), nextBaseDateTime.getValueAsString(), nextBaseDateTime.getValueAsString()); - theParams.add(param); - } - } - private void addUri_Uri(String theResourceType, Set theParams, RuntimeSearchParam theSearchParam, IBase theValue) { IPrimitiveType value = (IPrimitiveType) theValue; String valueAsString = value.getValueAsString();