Work on perf
This commit is contained in:
parent
9b1366734a
commit
233eb54710
|
@ -282,14 +282,9 @@ public class SearchBuilder {
|
||||||
doSetPids(q.getResultList());
|
doSetPids(q.getResultList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addPredicateLanguage(List<List<? extends IQueryParameterType>> theList) {
|
private void addPredicateLanguage(List<Predicate> thePredicates, Root<ResourceTable> theResourceTableRoot, List<List<? extends IQueryParameterType>> theList) {
|
||||||
for (List<? extends IQueryParameterType> nextList : theList) {
|
for (List<? extends IQueryParameterType> nextList : theList) {
|
||||||
|
|
||||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
|
||||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
|
||||||
Root<ResourceTable> from = cq.from(ResourceTable.class);
|
|
||||||
cq.select(from.get("myId").as(Long.class));
|
|
||||||
|
|
||||||
Set<String> values = new HashSet<String>();
|
Set<String> values = new HashSet<String>();
|
||||||
for (IQueryParameterType next : nextList) {
|
for (IQueryParameterType next : nextList) {
|
||||||
if (next instanceof StringParam) {
|
if (next instanceof StringParam) {
|
||||||
|
@ -307,21 +302,8 @@ public class SearchBuilder {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Predicate> predicates = new ArrayList<Predicate>();
|
Predicate predicate = theResourceTableRoot.get("myLanguage").as(String.class).in(values);
|
||||||
predicates.add(builder.equal(from.get("myResourceType"), myResourceName));
|
thePredicates.add(predicate);
|
||||||
predicates.add(from.get("myLanguage").as(String.class).in(values));
|
|
||||||
createPredicateResourceId(builder, cq, predicates, from.get("myId").as(Long.class));
|
|
||||||
createPredicateLastUpdatedForResourceTable(builder, from, predicates);
|
|
||||||
|
|
||||||
predicates.add(builder.isNull(from.get("myDeleted")));
|
|
||||||
|
|
||||||
cq.where(toArray(predicates));
|
|
||||||
|
|
||||||
TypedQuery<Long> q = myEntityManager.createQuery(cq);
|
|
||||||
doSetPids(q.getResultList());
|
|
||||||
if (doHaveNoResults()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -719,24 +701,6 @@ public class SearchBuilder {
|
||||||
throw new IllegalArgumentException("Param name: " + theParamName); // shouldn't happen
|
throw new IllegalArgumentException("Param name: " + theParamName); // shouldn't happen
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* CriteriaBuilder builder = myEntityManager.getCriteriaBuilder(); CriteriaQuery<Long> cq =
|
|
||||||
* builder.createQuery(Long.class); Root<ResourceTable> from = cq.from(ResourceTable.class);
|
|
||||||
* cq.select(from.get("myId").as(Long.class));
|
|
||||||
*
|
|
||||||
* Subquery<Long> subQ = cq.subquery(Long.class); Root<? extends BaseResourceIndexedSearchParam> subQfrom =
|
|
||||||
* subQ.from(theParamTable); subQ.select(subQfrom.get("myResourcePid").as(Long.class));
|
|
||||||
* Predicate subQname = builder.equal(subQfrom.get("myParamName"), theParamName); Predicate subQtype =
|
|
||||||
* builder.equal(subQfrom.get("myResourceType"), myResourceName);
|
|
||||||
* subQ.where(builder.and(subQtype, subQname));
|
|
||||||
*
|
|
||||||
* List<Predicate> predicates = new ArrayList<Predicate>();
|
|
||||||
* predicates.add(builder.not(builder.in(from.get("myId")).value(subQ)));
|
|
||||||
* predicates.add(builder.equal(from.get("myResourceType"),
|
|
||||||
* myResourceName)); predicates.add(builder.isNull(from.get("myDeleted"))); createPredicateResourceId(builder, cq,
|
|
||||||
* predicates, from.get("myId").as(Long.class));
|
|
||||||
*/
|
|
||||||
|
|
||||||
List<Pair<String, String>> notTags = Lists.newArrayList();
|
List<Pair<String, String>> notTags = Lists.newArrayList();
|
||||||
for (List<? extends IQueryParameterType> nextAndParams : theList) {
|
for (List<? extends IQueryParameterType> nextAndParams : theList) {
|
||||||
for (IQueryParameterType nextOrParams : nextAndParams) {
|
for (IQueryParameterType nextOrParams : nextAndParams) {
|
||||||
|
@ -1684,10 +1648,79 @@ public class SearchBuilder {
|
||||||
myParams = theParams;
|
myParams = theParams;
|
||||||
StopWatch w = new StopWatch();
|
StopWatch w = new StopWatch();
|
||||||
|
|
||||||
doInitializeSearch();
|
mySearchEntity = new Search();
|
||||||
return doReturnProvider();
|
mySearchEntity.setUuid(UUID.randomUUID().toString());
|
||||||
|
mySearchEntity.setCreated(new Date());
|
||||||
|
mySearchEntity.setTotalCount(-1);
|
||||||
|
mySearchEntity.setSearchParamMap(SerializationUtils.serialize(myParams));
|
||||||
|
mySearchEntity.setPreferredPageSize(myParams.getCount());
|
||||||
|
mySearchEntity.setSearchType(myParams.getEverythingMode() != null ? SearchTypeEnum.EVERYTHING : SearchTypeEnum.SEARCH);
|
||||||
|
mySearchEntity.setLastUpdated(myParams.getLastUpdated());
|
||||||
|
|
||||||
|
for (Include next : myParams.getIncludes()) {
|
||||||
|
mySearchEntity.getIncludes().add(new SearchInclude(mySearchEntity, next.getValue(), false, next.isRecurse()));
|
||||||
|
}
|
||||||
|
for (Include next : myParams.getRevIncludes()) {
|
||||||
|
mySearchEntity.getIncludes().add(new SearchInclude(mySearchEntity, next.getValue(), true, next.isRecurse()));
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Long> firstPage = loadSearchPage(theParams, 0, 999);
|
||||||
|
mySearchEntity.setTotalCount(firstPage.size());
|
||||||
|
|
||||||
|
myEntityManager.persist(mySearchEntity);
|
||||||
|
for (SearchInclude next : mySearchEntity.getIncludes()) {
|
||||||
|
myEntityManager.persist(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
IBundleProvider retVal = doReturnProvider();
|
||||||
|
|
||||||
|
ourLog.info("Search initial phase completed in {}ms", w);
|
||||||
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Long> loadSearchPage(SearchParameterMap theParams, int theFromIndex, int theToIndex) {
|
||||||
|
|
||||||
|
if (myFulltextSearchSvc == null) {
|
||||||
|
if (theParams.containsKey(Constants.PARAM_TEXT)) {
|
||||||
|
throw new InvalidRequestException("Fulltext search is not enabled on this service, can not process parameter: " + Constants.PARAM_TEXT);
|
||||||
|
} else if (theParams.containsKey(Constants.PARAM_CONTENT)) {
|
||||||
|
throw new InvalidRequestException("Fulltext search is not enabled on this service, can not process parameter: " + Constants.PARAM_CONTENT);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// FIXME: add from and to
|
||||||
|
List<Long> searchResultPids = myFulltextSearchSvc.search(myResourceName, theParams);
|
||||||
|
if (searchResultPids != null) {
|
||||||
|
if (searchResultPids.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
return searchResultPids;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||||
|
CriteriaQuery<Tuple> cq = builder.createTupleQuery();
|
||||||
|
Root<ResourceTable> from = cq.from(ResourceTable.class);
|
||||||
|
List<Predicate> predicates = new ArrayList<Predicate>();
|
||||||
|
predicates.add(builder.equal(from.get("myResourceType"), myResourceName));
|
||||||
|
predicates.add(builder.isNull(from.get("myDeleted")));
|
||||||
|
|
||||||
|
searchForIdsWithAndOr(theParams, predicates, from);
|
||||||
|
|
||||||
|
cq.where(builder.and(SearchBuilder.toArray(predicates)));
|
||||||
|
|
||||||
|
cq.multiselect(from.get("myId").as(Long.class));
|
||||||
|
TypedQuery<Tuple> query = myEntityManager.createQuery(cq);
|
||||||
|
query.setFirstResult(theFromIndex);
|
||||||
|
query.setMaxResults(theToIndex - theFromIndex);
|
||||||
|
|
||||||
|
List<Long> pids = new ArrayList<Long>();
|
||||||
|
for (Tuple next : query.getResultList()) {
|
||||||
|
pids.add(next.get(0, Long.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
return pids;
|
||||||
|
}
|
||||||
|
|
||||||
public IBundleProvider loadPage(SearchParameterMap theParams, int theFromIndex, int theToIndex) {
|
public IBundleProvider loadPage(SearchParameterMap theParams, int theFromIndex, int theToIndex) {
|
||||||
StopWatch sw = new StopWatch();
|
StopWatch sw = new StopWatch();
|
||||||
DateRangeParam lu = theParams.getLastUpdated();
|
DateRangeParam lu = theParams.getLastUpdated();
|
||||||
|
@ -1737,11 +1770,6 @@ public class SearchBuilder {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (theParams.isEmpty()) {
|
|
||||||
|
|
||||||
TypedQuery<Long> query = createSearchAllByTypeQuery(lu);
|
|
||||||
doSetPids(query.getResultList());
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (myFulltextSearchSvc == null) {
|
if (myFulltextSearchSvc == null) {
|
||||||
|
@ -1760,8 +1788,9 @@ public class SearchBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!theParams.isEmpty()) {
|
if (!theParams.isEmpty()) {
|
||||||
searchForIdsWithAndOr(theParams, lu);
|
// searchForIdsWithAndOr(theParams, lu);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1787,67 +1816,32 @@ public class SearchBuilder {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void searchForIdsWithAndOr(SearchParameterMap theParams, DateRangeParam theLastUpdated) {
|
private void searchForIdsWithAndOr(SearchParameterMap theParams, List<Predicate> thePredicates, Root<ResourceTable> theResourceTableRoot) {
|
||||||
SearchParameterMap params = theParams;
|
SearchParameterMap params = theParams;
|
||||||
if (params == null) {
|
if (params == null) {
|
||||||
params = new SearchParameterMap();
|
params = new SearchParameterMap();
|
||||||
}
|
}
|
||||||
myParams = theParams;
|
myParams = theParams;
|
||||||
|
|
||||||
doInitializeSearch();
|
|
||||||
|
|
||||||
// RuntimeResourceDefinition resourceDef = myContext.getResourceDefinition(myResourceType);
|
|
||||||
|
|
||||||
for (Entry<String, List<List<? extends IQueryParameterType>>> nextParamEntry : params.entrySet()) {
|
for (Entry<String, List<List<? extends IQueryParameterType>>> nextParamEntry : params.entrySet()) {
|
||||||
String nextParamName = nextParamEntry.getKey();
|
String nextParamName = nextParamEntry.getKey();
|
||||||
if (nextParamName.equals(BaseResource.SP_RES_ID)) {
|
if (nextParamName.equals(BaseResource.SP_RES_ID)) {
|
||||||
|
|
||||||
if (nextParamEntry.getValue().isEmpty()) {
|
addPredicateResourceId(thePredicates, theResourceTableRoot, nextParamEntry.getValue());
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
for (List<? extends IQueryParameterType> nextValue : nextParamEntry.getValue()) {
|
|
||||||
Set<Long> joinPids = new HashSet<Long>();
|
|
||||||
if (nextValue == null || nextValue.size() == 0) {
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
for (IQueryParameterType next : nextValue) {
|
|
||||||
String value = next.getValueAsQueryToken(myContext);
|
|
||||||
IIdType valueId = new IdDt(value);
|
|
||||||
|
|
||||||
try {
|
|
||||||
BaseHasResource entity = myCallingDao.readEntity(valueId);
|
|
||||||
if (entity.getDeleted() != null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
joinPids.add(entity.getId());
|
|
||||||
} catch (ResourceNotFoundException e) {
|
|
||||||
// This isn't an error, just means no result found
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (joinPids.isEmpty()) {
|
|
||||||
doSetPids(new HashSet<Long>());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addPredicateId(joinPids);
|
|
||||||
if (doHaveNoResults()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (nextParamName.equals(BaseResource.SP_RES_LANGUAGE)) {
|
} else if (nextParamName.equals(BaseResource.SP_RES_LANGUAGE)) {
|
||||||
|
|
||||||
addPredicateLanguage(nextParamEntry.getValue());
|
addPredicateLanguage(thePredicates, theResourceTableRoot, nextParamEntry.getValue());
|
||||||
|
|
||||||
} else if (nextParamName.equals(Constants.PARAM_HAS)) {
|
} else if (nextParamName.equals(Constants.PARAM_HAS)) {
|
||||||
|
|
||||||
addPredicateHas(nextParamEntry.getValue(), theLastUpdated);
|
// FIXME
|
||||||
|
addPredicateHas(nextParamEntry.getValue(), null);
|
||||||
|
|
||||||
} else if (nextParamName.equals(Constants.PARAM_TAG) || nextParamName.equals(Constants.PARAM_PROFILE) || nextParamName.equals(Constants.PARAM_SECURITY)) {
|
} else if (nextParamName.equals(Constants.PARAM_TAG) || nextParamName.equals(Constants.PARAM_PROFILE) || nextParamName.equals(Constants.PARAM_SECURITY)) {
|
||||||
|
|
||||||
addPredicateTag(nextParamEntry.getValue(), nextParamName, theLastUpdated);
|
// FIXME
|
||||||
|
addPredicateTag(nextParamEntry.getValue(), nextParamName, null);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -1925,14 +1919,44 @@ public class SearchBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doHaveNoResults()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addPredicateResourceId(List<Predicate> thePredicates, Root<ResourceTable> theResourceTableRoot, List<List<? extends IQueryParameterType>> theValues) {
|
||||||
|
for (List<? extends IQueryParameterType> nextValue : theValues) {
|
||||||
|
Set<Long> orPids = new HashSet<Long>();
|
||||||
|
for (IQueryParameterType next : nextValue) {
|
||||||
|
String value = next.getValueAsQueryToken(myContext);
|
||||||
|
IdDt valueAsId = new IdDt(value);
|
||||||
|
if (isNotBlank(value)) {
|
||||||
|
if (valueAsId.isIdPartValidLong()) {
|
||||||
|
orPids.add(valueAsId.getIdPartAsLong());
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
// BaseHasResource entity = myCallingDao.readEntity(valueId);
|
||||||
|
// if (entity.getDeleted() == null) {
|
||||||
|
// orPids.add(entity.getId());
|
||||||
|
// }
|
||||||
|
} catch (ResourceNotFoundException e) {
|
||||||
|
/*
|
||||||
|
* This isn't an error, just means no result found
|
||||||
|
* that matches the ID the client provided
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (orPids.size() > 0) {
|
||||||
|
Predicate nextPredicate = theResourceTableRoot.get("myId").as(Long.class).in(orPids);
|
||||||
|
thePredicates.add(nextPredicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setType(Class<? extends IBaseResource> theResourceType, String theResourceName) {
|
public void setType(Class<? extends IBaseResource> theResourceType, String theResourceName) {
|
||||||
myResourceType = theResourceType;
|
myResourceType = theResourceType;
|
||||||
myResourceName = theResourceName;
|
myResourceName = theResourceName;
|
||||||
|
|
|
@ -39,15 +39,15 @@ import ca.uhn.fhir.rest.server.IPagingProvider;
|
||||||
public class DatabaseBackedPagingProvider extends BasePagingProvider implements IPagingProvider {
|
public class DatabaseBackedPagingProvider extends BasePagingProvider implements IPagingProvider {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private PlatformTransactionManager thePlatformTransactionManager;
|
private PlatformTransactionManager myPlatformTransactionManager;
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISearchResultDao theSearchResultDao;
|
private ISearchResultDao mySearchResultDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
private EntityManager theEntityManager;
|
private EntityManager myEntityManager;
|
||||||
@Autowired
|
@Autowired
|
||||||
private FhirContext theContext;
|
private FhirContext myContext;
|
||||||
@Autowired
|
@Autowired
|
||||||
private IFhirSystemDao<?, ?> theDao;
|
private IFhirSystemDao<?, ?> myDao;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
|
@ -67,7 +67,7 @@ public class DatabaseBackedPagingProvider extends BasePagingProvider implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized IBundleProvider retrieveResultList(String theId) {
|
public synchronized IBundleProvider retrieveResultList(String theId) {
|
||||||
PersistedJpaBundleProvider provider = new PersistedJpaBundleProvider(theId, theDao);
|
PersistedJpaBundleProvider provider = new PersistedJpaBundleProvider(theId, myDao);
|
||||||
if (!provider.ensureSearchEntityLoaded()) {
|
if (!provider.ensureSearchEntityLoaded()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,22 +118,7 @@ public final class PersistedJpaBundleProvider implements IBundleProvider {
|
||||||
SearchBuilder sb = myDao.newSearchBuilder();
|
SearchBuilder sb = myDao.newSearchBuilder();
|
||||||
|
|
||||||
SearchParameterMap parameterMap = SerializationUtils.deserialize(mySearchEntity.getSearchParamMap());
|
SearchParameterMap parameterMap = SerializationUtils.deserialize(mySearchEntity.getSearchParamMap());
|
||||||
sb.loadPage(parameterMap, theFromIndex, theToIndex);
|
List<Long> pidsSubList = sb.loadSearchPage(parameterMap, theFromIndex, theToIndex);
|
||||||
|
|
||||||
Pageable page = toPage(theFromIndex, theToIndex);
|
|
||||||
if (page == null) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
Page<SearchResult> search = mySearchResultDao.findWithSearchUuid(mySearchEntity, page);
|
|
||||||
|
|
||||||
List<Long> pidsSubList = new ArrayList<Long>();
|
|
||||||
for (SearchResult next : search) {
|
|
||||||
pidsSubList.add(next.getResourcePid());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load includes
|
|
||||||
pidsSubList = new ArrayList<Long>(pidsSubList);
|
|
||||||
|
|
||||||
Set<Long> revIncludedPids = new HashSet<Long>();
|
Set<Long> revIncludedPids = new HashSet<Long>();
|
||||||
if (mySearchEntity.getSearchType() == SearchTypeEnum.SEARCH) {
|
if (mySearchEntity.getSearchType() == SearchTypeEnum.SEARCH) {
|
||||||
|
|
|
@ -522,27 +522,29 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchByIdParam() {
|
public void testSearchByIdParam() {
|
||||||
IIdType id1;
|
String id1;
|
||||||
{
|
{
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||||
id1 = myPatientDao.create(patient, mySrd).getId();
|
id1 = myPatientDao.create(patient, mySrd).getId().getValue();
|
||||||
}
|
}
|
||||||
IIdType id2;
|
String id2;
|
||||||
{
|
{
|
||||||
Organization patient = new Organization();
|
Organization patient = new Organization();
|
||||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||||
id2 = myOrganizationDao.create(patient, mySrd).getId();
|
id2 = myOrganizationDao.create(patient, mySrd).getId().getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||||
params.put("_id", new StringParam(id1.getIdPart()));
|
assertThat(toUnqualifiedVersionlessIdValues(myPatientDao.search(params)), contains(id1));
|
||||||
assertEquals(1, toList(myPatientDao.search(params)).size());
|
|
||||||
|
params.put("_id", new StringParam(id1));
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(myPatientDao.search(params)), contains(id1));
|
||||||
|
|
||||||
params.put("_id", new StringParam("9999999999999999"));
|
params.put("_id", new StringParam("9999999999999999"));
|
||||||
assertEquals(0, toList(myPatientDao.search(params)).size());
|
assertEquals(0, toList(myPatientDao.search(params)).size());
|
||||||
|
|
||||||
params.put("_id", new StringParam(id2.getIdPart()));
|
params.put("_id", new StringParam(id2));
|
||||||
assertEquals(0, toList(myPatientDao.search(params)).size());
|
assertEquals(0, toList(myPatientDao.search(params)).size());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue