Added pre-fetch for concept designations, improved paging for expanded ValueSets, and columns on TermValueSet for number of concepts and designations.
This commit is contained in:
parent
1ef70a0fca
commit
b42b598d01
|
@ -40,8 +40,8 @@ public interface ITermValueSetConceptDao extends JpaRepository<TermValueSetConce
|
|||
@Modifying
|
||||
void deleteByTermValueSetId(@Param("pid") Long theValueSetId);
|
||||
|
||||
@Query("SELECT vsc from TermValueSetConcept vsc WHERE vsc.myValueSet.myId = :pid")
|
||||
Slice<TermValueSetConcept> findByTermValueSetId(Pageable thePage, @Param("pid") Long theValueSetId);
|
||||
@Query("SELECT vsc from TermValueSetConcept vsc LEFT OUTER JOIN FETCH vsc.myDesignations WHERE vsc.myValueSet.myId = :pid")
|
||||
Slice<TermValueSetConcept> findByTermValueSetIdAndPreFetchDesignations(Pageable thePage, @Param("pid") Long theValueSetId);
|
||||
|
||||
@Query("SELECT vsc FROM TermValueSetConcept vsc WHERE vsc.myValueSet.myId = :pid AND vsc.mySystem = :system_url AND vsc.myCode = :codeval")
|
||||
Optional<TermValueSetConcept> findByTermValueSetIdSystemAndCode(@Param("pid") Long theValueSetId, @Param("system_url") String theSystem, @Param("codeval") String theCode);
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.apache.commons.lang3.builder.EqualsBuilder;
|
|||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.persistence.*;
|
||||
|
@ -43,6 +44,8 @@ import static org.apache.commons.lang3.StringUtils.length;
|
|||
public class TermValueSet implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final int MAX_TOTAL_LENGTH = 19;
|
||||
|
||||
public static final int MAX_EXPANSION_STATUS_LENGTH = 50;
|
||||
public static final int MAX_NAME_LENGTH = 200;
|
||||
public static final int MAX_URL_LENGTH = 200;
|
||||
|
@ -69,6 +72,14 @@ public class TermValueSet implements Serializable {
|
|||
@OneToMany(mappedBy = "myValueSet")
|
||||
private List<TermValueSetConcept> myConcepts;
|
||||
|
||||
@Column(name = "TOTAL_CONCEPTS", nullable = false, length = MAX_TOTAL_LENGTH)
|
||||
@ColumnDefault("0")
|
||||
private Long myTotalConcepts;
|
||||
|
||||
@Column(name = "TOTAL_CONCEPT_DESIGNATIONS", nullable = false, length = MAX_TOTAL_LENGTH)
|
||||
@ColumnDefault("0")
|
||||
private Long myTotalConceptDesignations;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "EXPANSION_STATUS", nullable = false, length = MAX_EXPANSION_STATUS_LENGTH)
|
||||
private TermValueSetPreExpansionStatusEnum myExpansionStatus;
|
||||
|
@ -76,6 +87,8 @@ public class TermValueSet implements Serializable {
|
|||
public TermValueSet() {
|
||||
super();
|
||||
myExpansionStatus = TermValueSetPreExpansionStatusEnum.NOT_EXPANDED;
|
||||
myTotalConcepts = 0L;
|
||||
myTotalConceptDesignations = 0L;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
|
@ -120,6 +133,48 @@ public class TermValueSet implements Serializable {
|
|||
return myConcepts;
|
||||
}
|
||||
|
||||
public Long getTotalConcepts() {
|
||||
return myTotalConcepts;
|
||||
}
|
||||
|
||||
public TermValueSet setTotalConcepts(Long theTotalConcepts) {
|
||||
myTotalConcepts = theTotalConcepts;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TermValueSet decrementTotalConcepts() {
|
||||
if (myTotalConcepts > 0) {
|
||||
myTotalConcepts--;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public TermValueSet incrementTotalConcepts() {
|
||||
myTotalConcepts++;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Long getTotalConceptDesignations() {
|
||||
return myTotalConceptDesignations;
|
||||
}
|
||||
|
||||
public TermValueSet setTotalConceptDesignations(Long theTotalConceptDesignations) {
|
||||
myTotalConceptDesignations = theTotalConceptDesignations;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TermValueSet decrementTotalConceptDesignations() {
|
||||
if (myTotalConceptDesignations > 0) {
|
||||
myTotalConceptDesignations--;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public TermValueSet incrementTotalConceptDesignations() {
|
||||
myTotalConceptDesignations++;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TermValueSetPreExpansionStatusEnum getExpansionStatus() {
|
||||
return myExpansionStatus;
|
||||
}
|
||||
|
@ -157,6 +212,8 @@ public class TermValueSet implements Serializable {
|
|||
.append("myResourcePid", myResourcePid)
|
||||
.append("myName", myName)
|
||||
.append(myConcepts != null ? ("myConcepts - size=" + myConcepts.size()) : ("myConcepts=(null)"))
|
||||
.append("myTotalConcepts", myTotalConcepts)
|
||||
.append("myTotalConceptDesignations", myTotalConceptDesignations)
|
||||
.append("myExpansionStatus", myExpansionStatus)
|
||||
.toString();
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import ca.uhn.fhir.jpa.dao.data.*;
|
|||
import ca.uhn.fhir.jpa.entity.*;
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl;
|
||||
import ca.uhn.fhir.jpa.util.ScrollableResultsIterator;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
|
@ -524,7 +525,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
|||
}
|
||||
|
||||
private void populateExpansionComponent(ValueSet.ValueSetExpansionComponent theExpansionComponent, TermValueSet theTermValueSet, int theOffset, int theCount) {
|
||||
int total = myValueSetConceptDao.countByTermValueSetId(theTermValueSet.getId());
|
||||
int total = theTermValueSet.getTotalConcepts().intValue();
|
||||
theExpansionComponent.setTotal(total);
|
||||
theExpansionComponent.setOffset(theOffset);
|
||||
theExpansionComponent.addParameter().setName("offset").setValue(new IntegerType(theOffset));
|
||||
|
@ -539,72 +540,59 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
|||
|
||||
private void expandConcepts(ValueSet.ValueSetExpansionComponent theExpansionComponent, TermValueSet theTermValueSet, int theOffset, int theCount) {
|
||||
int conceptsExpanded = 0;
|
||||
for (int i = theOffset; i < (theOffset + theCount); i++) {
|
||||
final int page = i;
|
||||
Supplier<Slice<TermValueSetConcept>> loader = () -> myValueSetConceptDao.findByTermValueSetId(PageRequest.of(page, 1), theTermValueSet.getId());
|
||||
int toIndex = theOffset + theCount;
|
||||
Supplier<Slice<TermValueSetConcept>> loader = () -> myValueSetConceptDao.findByTermValueSetIdAndPreFetchDesignations(SearchCoordinatorSvcImpl.toPage(theOffset, toIndex), theTermValueSet.getId());
|
||||
Slice<TermValueSetConcept> slice = loader.get();
|
||||
if (!slice.hasContent()) {
|
||||
logConceptsExpanded(theTermValueSet, conceptsExpanded);
|
||||
return;
|
||||
}
|
||||
|
||||
Slice<TermValueSetConcept> slice = loader.get();
|
||||
if (!slice.hasContent()) {
|
||||
break;
|
||||
}
|
||||
for (TermValueSetConcept concept : slice.getContent()) {
|
||||
ValueSet.ValueSetExpansionContainsComponent containsComponent = theExpansionComponent.addContains();
|
||||
containsComponent.setSystem(concept.getSystem());
|
||||
containsComponent.setCode(concept.getCode());
|
||||
containsComponent.setDisplay(concept.getDisplay());
|
||||
|
||||
for (TermValueSetConcept concept : slice.getContent()) {
|
||||
ValueSet.ValueSetExpansionContainsComponent containsComponent = theExpansionComponent.addContains();
|
||||
containsComponent.setSystem(concept.getSystem());
|
||||
containsComponent.setCode(concept.getCode());
|
||||
containsComponent.setDisplay(concept.getDisplay());
|
||||
// TODO: DM 2019-08-17 - Implement includeDesignations parameter for $expand operation to make this optional.
|
||||
expandDesignations(theTermValueSet, concept, containsComponent);
|
||||
|
||||
// TODO: DM 2019-08-17 - Implement includeDesignations parameter for $expand operation to make this optional.
|
||||
expandDesignations(theTermValueSet, concept, containsComponent);
|
||||
|
||||
if (++conceptsExpanded % 250 == 0) {
|
||||
ourLog.info("Have expanded {} concepts in ValueSet[{}]", conceptsExpanded, theTermValueSet.getUrl());
|
||||
}
|
||||
}
|
||||
|
||||
if (!slice.hasNext()) {
|
||||
break;
|
||||
if (++conceptsExpanded % 250 == 0) {
|
||||
logConceptsExpanded(theTermValueSet, conceptsExpanded);
|
||||
}
|
||||
}
|
||||
|
||||
if (conceptsExpanded > 0) {
|
||||
ourLog.info("Have expanded {} concepts in ValueSet[{}]", conceptsExpanded, theTermValueSet.getUrl());
|
||||
logConceptsExpanded(theTermValueSet, conceptsExpanded);
|
||||
}
|
||||
|
||||
private void logConceptsExpanded(TermValueSet theTermValueSet, int theConceptsExpanded) {
|
||||
if (theConceptsExpanded > 0) {
|
||||
ourLog.info("Have expanded {} concepts in ValueSet[{}]", theConceptsExpanded, theTermValueSet.getUrl());
|
||||
}
|
||||
}
|
||||
|
||||
private void expandDesignations(TermValueSet theValueSet, TermValueSetConcept theConcept, ValueSet.ValueSetExpansionContainsComponent theContainsComponent) {
|
||||
int designationsExpanded = 0;
|
||||
int index = 0;
|
||||
while (true) {
|
||||
final int page = index++;
|
||||
Supplier<Slice<TermValueSetConceptDesignation>> loader = () -> myValueSetConceptDesignationDao.findByTermValueSetConceptId(PageRequest.of(page, 1000), theConcept.getId());
|
||||
for (TermValueSetConceptDesignation designation : theConcept.getDesignations()) {
|
||||
ValueSet.ConceptReferenceDesignationComponent designationComponent = theContainsComponent.addDesignation();
|
||||
designationComponent.setLanguage(designation.getLanguage());
|
||||
designationComponent.setUse(new Coding(
|
||||
designation.getUseSystem(),
|
||||
designation.getUseCode(),
|
||||
designation.getUseDisplay()));
|
||||
designationComponent.setValue(designation.getValue());
|
||||
|
||||
Slice<TermValueSetConceptDesignation> slice = loader.get();
|
||||
if (!slice.hasContent()) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (TermValueSetConceptDesignation designation : slice.getContent()) {
|
||||
ValueSet.ConceptReferenceDesignationComponent designationComponent = theContainsComponent.addDesignation();
|
||||
designationComponent.setLanguage(designation.getLanguage());
|
||||
designationComponent.setUse(new Coding(
|
||||
designation.getUseSystem(),
|
||||
designation.getUseCode(),
|
||||
designation.getUseDisplay()));
|
||||
designationComponent.setValue(designation.getValue());
|
||||
|
||||
if (++designationsExpanded % 250 == 0) {
|
||||
ourLog.info("Have expanded {} designations for Concept[{}|{}] in ValueSet[{}]", designationsExpanded, theConcept.getSystem(), theConcept.getCode(), theValueSet.getUrl());
|
||||
}
|
||||
}
|
||||
|
||||
if (!slice.hasNext()) {
|
||||
break;
|
||||
if (++designationsExpanded % 250 == 0) {
|
||||
logDesignationsExpanded(theValueSet, theConcept, designationsExpanded);
|
||||
}
|
||||
}
|
||||
|
||||
if (designationsExpanded > 0) {
|
||||
ourLog.info("Have expanded {} designations for Concept[{}|{}] in ValueSet[{}]", designationsExpanded, theConcept.getSystem(), theConcept.getCode(), theValueSet.getUrl());
|
||||
logDesignationsExpanded(theValueSet, theConcept, designationsExpanded);
|
||||
}
|
||||
|
||||
private void logDesignationsExpanded(TermValueSet theValueSet, TermValueSetConcept theConcept, int theDesignationsExpanded) {
|
||||
if (theDesignationsExpanded > 0) {
|
||||
ourLog.info("Have expanded {} designations for Concept[{}|{}] in ValueSet[{}]", theDesignationsExpanded, theConcept.getSystem(), theConcept.getCode(), theValueSet.getUrl());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -79,8 +79,10 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator {
|
|||
ourLog.info("Excluding [{}|{}] from ValueSet[{}]", concept.getSystem(), concept.getCode(), myTermValueSet.getUrl());
|
||||
for (TermValueSetConceptDesignation designation : concept.getDesignations()) {
|
||||
myValueSetConceptDesignationDao.deleteById(designation.getId());
|
||||
myTermValueSet.decrementTotalConceptDesignations();
|
||||
}
|
||||
myValueSetConceptDao.deleteById(concept.getId());
|
||||
myTermValueSet.decrementTotalConcepts();
|
||||
ourLog.info("Done excluding [{}|{}] from ValueSet[{}]", concept.getSystem(), concept.getCode(), myTermValueSet.getUrl());
|
||||
|
||||
ourLog.info("Flushing...");
|
||||
|
@ -102,6 +104,7 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator {
|
|||
concept.setDisplay(theDisplay);
|
||||
}
|
||||
myValueSetConceptDao.save(concept);
|
||||
myTermValueSet.incrementTotalConcepts();
|
||||
|
||||
if (myConceptsSaved++ % 250 == 0) { // TODO: DM 2019-08-23 - This message never appears in the log. Fix it!
|
||||
ourLog.info("Have pre-expanded {} concepts in ValueSet[{}]", myConceptsSaved, myTermValueSet.getUrl());
|
||||
|
@ -126,6 +129,7 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator {
|
|||
}
|
||||
designation.setValue(theDesignation.getValue());
|
||||
myValueSetConceptDesignationDao.save(designation);
|
||||
myTermValueSet.incrementTotalConceptDesignations();
|
||||
|
||||
if (myDesignationsSaved++ % 250 == 0) { // TODO: DM 2019-08-23 - This message never appears in the log. Fix it!
|
||||
ourLog.info("Have pre-expanded {} designations for Concept[{}|{}] in ValueSet[{}]", myDesignationsSaved, theConcept.getSystem(), theConcept.getCode(), myTermValueSet.getUrl());
|
||||
|
|
|
@ -312,6 +312,7 @@ public class SearchCoordinatorSvcImplTest {
|
|||
public void testGetPage() {
|
||||
Pageable page = SearchCoordinatorSvcImpl.toPage(50, 73);
|
||||
assertEquals(50, page.getOffset());
|
||||
assertEquals(23, page.getPageSize());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -36,6 +36,7 @@ import java.util.Optional;
|
|||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.times;
|
||||
|
@ -643,9 +644,12 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
|
|||
ValueSet expandedValueSet = myTermSvc.expandValueSet(valueSet, myDaoConfig.getPreExpandValueSetsDefaultOffsetExperimental(), myDaoConfig.getPreExpandValueSetsDefaultCountExperimental());
|
||||
ourLog.info("Expanded ValueSet:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expandedValueSet));
|
||||
|
||||
Long termValueSetId = myTermValueSetDao.findByResourcePid(myExtensionalVsIdOnResourceTable).get().getId();
|
||||
TermValueSet termValueSet = myTermValueSetDao.findByResourcePid(myExtensionalVsIdOnResourceTable).get();
|
||||
Long termValueSetId = termValueSet.getId();
|
||||
assertEquals(3, myTermValueSetConceptDesignationDao.countByTermValueSetId(termValueSetId).intValue());
|
||||
assertEquals(3, termValueSet.getTotalConceptDesignations().intValue());
|
||||
assertEquals(24, myTermValueSetConceptDao.countByTermValueSetId(termValueSetId).intValue());
|
||||
assertEquals(24, termValueSet.getTotalConcepts().intValue());
|
||||
|
||||
new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() {
|
||||
@Override
|
||||
|
@ -677,9 +681,12 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
|
|||
ValueSet expandedValueSet = myTermSvc.expandValueSet(valueSet, myDaoConfig.getPreExpandValueSetsDefaultOffsetExperimental(), myDaoConfig.getPreExpandValueSetsDefaultCountExperimental());
|
||||
ourLog.info("Expanded ValueSet:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expandedValueSet));
|
||||
|
||||
Long termValueSetId = myTermValueSetDao.findByResourcePid(myExtensionalVsIdOnResourceTable).get().getId();
|
||||
TermValueSet termValueSet = myTermValueSetDao.findByResourcePid(myExtensionalVsIdOnResourceTable).get();
|
||||
Long termValueSetId = termValueSet.getId();
|
||||
assertEquals(3, myTermValueSetConceptDesignationDao.countByTermValueSetId(termValueSetId).intValue());
|
||||
assertEquals(3, termValueSet.getTotalConceptDesignations().intValue());
|
||||
assertEquals(24, myTermValueSetConceptDao.countByTermValueSetId(termValueSetId).intValue());
|
||||
assertEquals(24, termValueSet.getTotalConcepts().intValue());
|
||||
|
||||
new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() {
|
||||
@Override
|
||||
|
@ -741,9 +748,17 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
|
|||
|
||||
myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
|
||||
|
||||
myCaptureQueriesListener.clear();
|
||||
|
||||
ValueSet expandedValueSet = myTermSvc.expandValueSet(valueSet, myDaoConfig.getPreExpandValueSetsDefaultOffsetExperimental(), myDaoConfig.getPreExpandValueSetsDefaultCountExperimental());
|
||||
ourLog.info("Expanded ValueSet:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expandedValueSet));
|
||||
|
||||
myCaptureQueriesListener.logSelectQueriesForCurrentThread();
|
||||
assertEquals(3, myCaptureQueriesListener.getSelectQueriesForCurrentThread().size());
|
||||
assertThat(myCaptureQueriesListener.getUpdateQueriesForCurrentThread(), empty());
|
||||
assertThat(myCaptureQueriesListener.getInsertQueriesForCurrentThread(), empty());
|
||||
assertThat(myCaptureQueriesListener.getDeleteQueriesForCurrentThread(), empty());
|
||||
|
||||
assertEquals(codeSystem.getConcept().size(), expandedValueSet.getExpansion().getTotal());
|
||||
assertEquals(myDaoConfig.getPreExpandValueSetsDefaultOffsetExperimental(), expandedValueSet.getExpansion().getOffset());
|
||||
assertEquals(2, expandedValueSet.getExpansion().getParameter().size());
|
||||
|
|
|
@ -87,6 +87,12 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
|||
.addForeignKey("FK_TRM_VSCD_VS_PID")
|
||||
.toColumn("VALUESET_PID")
|
||||
.references("TRM_VALUESET", "PID");
|
||||
|
||||
// TermValueSet
|
||||
version.startSectionWithMessage("Processing table: TRM_VALUESET");
|
||||
Builder.BuilderWithTableName termValueSetTable = version.onTable("TRM_VALUESET");
|
||||
termValueSetTable.addColumn("TOTAL_CONCEPTS").nonNullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
|
||||
termValueSetTable.addColumn("TOTAL_CONCEPT_DESIGNATIONS").nonNullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
|
||||
}
|
||||
|
||||
protected void init400() {
|
||||
|
|
Loading…
Reference in New Issue