Merge pull request #1695 from jamesagnew/ks-20200131-near-search-http
Ks 20200131 near search http
This commit is contained in:
commit
7faf8932cf
|
@ -65,6 +65,7 @@ import org.apache.commons.lang3.Validate;
|
|||
import org.hibernate.ScrollMode;
|
||||
import org.hibernate.ScrollableResults;
|
||||
import org.hibernate.query.Query;
|
||||
import org.hl7.fhir.dstu3.model.Location;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -160,6 +161,10 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
// Remove any empty parameters
|
||||
theParams.clean();
|
||||
|
||||
if (myResourceType == Location.class) {
|
||||
theParams.setLocationDistance();
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if there is a unique key associated with the set
|
||||
* of parameters passed in
|
||||
|
@ -181,7 +186,6 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Iterator<Long> createCountQuery(SearchParameterMap theParams, String theSearchUuid, RequestDetails theRequest) {
|
||||
init(theParams, theSearchUuid);
|
||||
|
|
|
@ -5,6 +5,7 @@ import ca.uhn.fhir.jpa.dao.data.ISearchDao;
|
|||
import ca.uhn.fhir.jpa.entity.Search;
|
||||
import ca.uhn.fhir.jpa.provider.r4.ResourceProviderR4Test;
|
||||
import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl;
|
||||
import ca.uhn.fhir.jpa.util.CoordCalculatorTest;
|
||||
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
|
@ -65,6 +66,7 @@ import java.math.BigDecimal;
|
|||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
|
@ -4282,6 +4284,55 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNearSearchApproximate() {
|
||||
Location loc = new Location();
|
||||
double latitude = CoordCalculatorTest.LATITUDE_UHN;
|
||||
double longitude = CoordCalculatorTest.LONGITUDE_UHN;
|
||||
Location.LocationPositionComponent position = new Location.LocationPositionComponent().setLatitude(latitude).setLongitude(longitude);
|
||||
loc.setPosition(position);
|
||||
IIdType locId = ourClient.create().resource(loc).execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
{ // In the box
|
||||
double bigEnoughDistance = CoordCalculatorTest.DISTANCE_KM_CHIN_TO_UHN * 2;
|
||||
String url = "/Location?" +
|
||||
Location.SP_NEAR + "=" + CoordCalculatorTest.LATITUDE_CHIN + URLEncoder.encode(":") + CoordCalculatorTest.LONGITUDE_CHIN +
|
||||
"&" +
|
||||
Location.SP_NEAR_DISTANCE + "=" + bigEnoughDistance + URLEncoder.encode("|http://unitsofmeasure.org|km");
|
||||
|
||||
Bundle actual = ourClient
|
||||
.search()
|
||||
.byUrl(ourServerBase + "/" + url)
|
||||
.encodedJson()
|
||||
.prettyPrint()
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
|
||||
assertEquals(1, actual.getEntry().size());
|
||||
assertEquals(locId.getIdPart(), actual.getEntry().get(0).getResource().getIdElement().getIdPart());
|
||||
}
|
||||
{ // Outside the box
|
||||
double tooSmallDistance = CoordCalculatorTest.DISTANCE_KM_CHIN_TO_UHN / 2;
|
||||
String url = "/Location?" +
|
||||
Location.SP_NEAR + "=" + CoordCalculatorTest.LATITUDE_CHIN + URLEncoder.encode(":") + CoordCalculatorTest.LONGITUDE_CHIN +
|
||||
"&" +
|
||||
Location.SP_NEAR_DISTANCE + "=" + tooSmallDistance + URLEncoder.encode("|http://unitsofmeasure.org|km");
|
||||
|
||||
myCaptureQueriesListener.clear();
|
||||
Bundle actual = ourClient
|
||||
.search()
|
||||
.byUrl(ourServerBase + "/" + url)
|
||||
.encodedJson()
|
||||
.prettyPrint()
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
myCaptureQueriesListener.logSelectQueries();
|
||||
|
||||
assertEquals(0, actual.getEntry().size());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String toStr(Date theDate) {
|
||||
return new InstantDt(theDate).getValueAsString();
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ public class MatchUrlServiceTest extends BaseJpaTest {
|
|||
Location.SP_NEAR + "=1000.0:2000.0" +
|
||||
"&" +
|
||||
Location.SP_NEAR_DISTANCE + "=" + kmDistance + "|http://unitsofmeasure.org|km", ourCtx.getResourceDefinition("Location"));
|
||||
map.setLocationDistance();
|
||||
|
||||
QuantityParam nearDistanceParam = map.getNearDistanceParam();
|
||||
assertEquals(1, map.size());
|
||||
|
@ -74,6 +75,8 @@ public class MatchUrlServiceTest extends BaseJpaTest {
|
|||
"&" +
|
||||
Location.SP_NEAR_DISTANCE + "=2|http://unitsofmeasure.org|km",
|
||||
ourCtx.getResourceDefinition("Location"));
|
||||
map.setLocationDistance();
|
||||
|
||||
fail();
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("Only one " + Location.SP_NEAR_DISTANCE + " parameter may be present", e.getMessage());
|
||||
|
@ -89,7 +92,8 @@ public class MatchUrlServiceTest extends BaseJpaTest {
|
|||
"," +
|
||||
"2|http://unitsofmeasure.org|km",
|
||||
ourCtx.getResourceDefinition("Location"));
|
||||
map.setLoadSynchronous(true);
|
||||
map.setLocationDistance();
|
||||
|
||||
fail();
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("Only one " + Location.SP_NEAR_DISTANCE + " parameter may be present", e.getMessage());
|
||||
|
|
|
@ -26,13 +26,11 @@ import ca.uhn.fhir.context.RuntimeSearchParam;
|
|||
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterAnd;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Location;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.QualifiedParamList;
|
||||
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
|
||||
import ca.uhn.fhir.rest.param.DateRangeParam;
|
||||
import ca.uhn.fhir.rest.param.ParameterUtil;
|
||||
import ca.uhn.fhir.rest.param.QuantityAndListParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.util.ReflectionUtil;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
|
@ -115,9 +113,6 @@ public class MatchUrlService {
|
|||
} else if (Constants.PARAM_SOURCE.equals(nextParamName)) {
|
||||
IQueryParameterAnd<?> param = ParameterUtil.parseQueryParams(myContext, RestSearchParameterTypeEnum.TOKEN, nextParamName, paramList);
|
||||
paramMap.add(nextParamName, param);
|
||||
} else if (Location.SP_NEAR_DISTANCE.equals(nextParamName)) {
|
||||
QuantityAndListParam nearDistanceAndListParam = (QuantityAndListParam) ParameterUtil.parseQueryParams(myContext, RestSearchParameterTypeEnum.QUANTITY, nextParamName, paramList);
|
||||
paramMap.setNearDistanceParam(nearDistanceAndListParam);
|
||||
} else if (nextParamName.startsWith("_")) {
|
||||
// ignore these since they aren't search params (e.g. _sort)
|
||||
} else {
|
||||
|
|
|
@ -5,15 +5,17 @@ import ca.uhn.fhir.model.api.IQueryParameterAnd;
|
|||
import ca.uhn.fhir.model.api.IQueryParameterOr;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Location;
|
||||
import ca.uhn.fhir.rest.api.*;
|
||||
import ca.uhn.fhir.rest.param.*;
|
||||
import ca.uhn.fhir.rest.param.DateParam;
|
||||
import ca.uhn.fhir.rest.param.DateRangeParam;
|
||||
import ca.uhn.fhir.rest.param.QuantityParam;
|
||||
import ca.uhn.fhir.util.ObjectUtil;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import org.hl7.fhir.dstu3.model.Location;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
@ -495,29 +497,38 @@ public class SearchParameterMap implements Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
public void setNearDistanceParam(QuantityAndListParam theQuantityAndListParam) {
|
||||
List<QuantityOrListParam> orTokens = theQuantityAndListParam.getValuesAsQueryTokens();
|
||||
if (orTokens.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (orTokens.size() > 1) {
|
||||
throw new IllegalArgumentException("Only one " + Location.SP_NEAR_DISTANCE + " parameter may be present");
|
||||
}
|
||||
QuantityOrListParam quantityOrListParam = orTokens.get(0);
|
||||
List<QuantityParam> tokens = quantityOrListParam.getValuesAsQueryTokens();
|
||||
if (tokens.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (tokens.size() > 1) {
|
||||
throw new IllegalArgumentException("Only one " + Location.SP_NEAR_DISTANCE + " parameter may be present");
|
||||
}
|
||||
myNearDistanceParam = tokens.get(0);
|
||||
public void setNearDistanceParam(QuantityParam theQuantityParam) {
|
||||
myNearDistanceParam = theQuantityParam;
|
||||
}
|
||||
|
||||
public QuantityParam getNearDistanceParam() {
|
||||
return myNearDistanceParam;
|
||||
}
|
||||
|
||||
public void setLocationDistance() {
|
||||
if (containsKey(Location.SP_NEAR_DISTANCE)) {
|
||||
List<List<IQueryParameterType>> paramAndList = get(Location.SP_NEAR_DISTANCE);
|
||||
|
||||
if (paramAndList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (paramAndList.size() > 1) {
|
||||
throw new IllegalArgumentException("Only one " + ca.uhn.fhir.model.dstu2.resource.Location.SP_NEAR_DISTANCE + " parameter may be present");
|
||||
}
|
||||
List<IQueryParameterType> paramOrList = paramAndList.get(0);
|
||||
if (paramOrList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (paramOrList.size() > 1) {
|
||||
throw new IllegalArgumentException("Only one " + ca.uhn.fhir.model.dstu2.resource.Location.SP_NEAR_DISTANCE + " parameter may be present");
|
||||
}
|
||||
setNearDistanceParam((QuantityParam) paramOrList.get(0));
|
||||
|
||||
// Need to remove near-distance or it we'll get a hashcode predicate for it
|
||||
remove(Location.SP_NEAR_DISTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
public enum EverythingModeEnum {
|
||||
/*
|
||||
* Don't reorder! We rely on the ordinals
|
||||
|
|
|
@ -40,6 +40,7 @@ import ca.uhn.fhir.rest.param.StringParam;
|
|||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.util.MetaUtil;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
import org.hl7.fhir.dstu3.model.Location;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
@ -88,7 +89,7 @@ public class InMemoryResourceMatcher {
|
|||
if (searchParameterMap.getLastUpdated() != null) {
|
||||
return InMemoryMatchResult.unsupportedFromParameterAndReason(Constants.PARAM_LASTUPDATED, InMemoryMatchResult.STANDARD_PARAMETER);
|
||||
}
|
||||
if (searchParameterMap.getNearDistanceParam() != null) {
|
||||
if (searchParameterMap.containsKey(Location.SP_NEAR)) {
|
||||
return InMemoryMatchResult.unsupportedFromReason(InMemoryMatchResult.LOCATION_NEAR);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue