diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/BaseParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/BaseParam.java
index 66e08a5ab70..88c00be3160 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/BaseParam.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/BaseParam.java
@@ -40,7 +40,7 @@ abstract class BaseParam implements IQueryParameterType {
@Override
public final String getQueryParameterQualifier() {
- if (myMissing != null) {
+ if (myMissing != null && myMissing.booleanValue()) {
return Constants.PARAMQUALIFIER_MISSING;
}
return doGetQueryParameterQualifier();
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/StringParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/StringParam.java
index fc475699ae4..56093b27194 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/StringParam.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/StringParam.java
@@ -19,8 +19,7 @@ package ca.uhn.fhir.rest.param;
* limitations under the License.
* #L%
*/
-
-import static org.apache.commons.lang3.StringUtils.*;
+import static org.apache.commons.lang3.StringUtils.defaultString;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
@@ -34,6 +33,7 @@ public class StringParam extends BaseParam implements IQueryParameterType {
private boolean myExact;
private String myValue;
+ private boolean myContains;
public StringParam() {
}
@@ -51,6 +51,8 @@ public class StringParam extends BaseParam implements IQueryParameterType {
String doGetQueryParameterQualifier() {
if (isExact()) {
return Constants.PARAMQUALIFIER_STRING_EXACT;
+ } else if (isContains()) {
+ return Constants.PARAMQUALIFIER_STRING_CONTAINS;
} else {
return null;
}
@@ -68,6 +70,11 @@ public class StringParam extends BaseParam implements IQueryParameterType {
} else {
setExact(false);
}
+ if (Constants.PARAMQUALIFIER_STRING_CONTAINS.equals(theQualifier)) {
+ setContains(true);
+ } else {
+ setContains(false);
+ }
myValue = ParameterUtil.unescape(theValue);
}
@@ -91,12 +98,25 @@ public class StringParam extends BaseParam implements IQueryParameterType {
return myExact;
}
- public void setExact(boolean theExact) {
+ public StringParam setExact(boolean theExact) {
myExact = theExact;
+ if (myExact) {
+ setContains(false);
+ setMissing(null);
+ }
+ return this;
}
- public void setValue(String theValue) {
+ /**
+ * String parameter modifier :contains
+ */
+ public boolean isContains() {
+ return myContains;
+ }
+
+ public StringParam setValue(String theValue) {
myValue = theValue;
+ return this;
}
@Override
@@ -106,10 +126,25 @@ public class StringParam extends BaseParam implements IQueryParameterType {
if (myExact) {
builder.append("exact", myExact);
}
+ if (myContains) {
+ builder.append("contains", myContains);
+ }
if (getMissing() != null) {
builder.append("missing", getMissing().booleanValue());
}
return builder.toString();
}
+ /**
+ * String parameter modifier :contains
+ */
+ public StringParam setContains(boolean theContains) {
+ myContains = theContains;
+ if (myContains) {
+ setExact(false);
+ setMissing(null);
+ }
+ return this;
+ }
+
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java
index 7177f1d4cbe..e020a1bc936 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java
@@ -127,6 +127,7 @@ public class Constants {
public static final String PARAMQUALIFIER_MISSING_FALSE = "false";
public static final String PARAMQUALIFIER_MISSING_TRUE = "true";
public static final String PARAMQUALIFIER_STRING_EXACT = ":exact";
+ public static final String PARAMQUALIFIER_STRING_CONTAINS = ":contains";
public static final String PARAMQUALIFIER_TOKEN_TEXT = ":text";
public static final int STATUS_HTTP_200_OK = 200;
public static final int STATUS_HTTP_201_CREATED = 201;
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirSearchDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirSearchDao.java
index f2dda1ff35f..034b7cea2e8 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirSearchDao.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirSearchDao.java
@@ -101,7 +101,7 @@ public class FhirSearchDao extends BaseHapiFhirDao implements ISe
for (List extends IQueryParameterType> nextAndList : theParams.get(nextParamName)) {
for (Iterator extends IQueryParameterType> orIterator = nextAndList.iterator(); orIterator.hasNext();) {
IQueryParameterType nextParam = orIterator.next();
- if (nextParam instanceof TokenParam && false) {
+ if (nextParam instanceof TokenParam) {
TokenParam nextTokenParam = (TokenParam) nextParam;
if (nextTokenParam.isText()) {
orIterator.remove();
@@ -112,27 +112,26 @@ public class FhirSearchDao extends BaseHapiFhirDao implements ISe
if (isNotBlank(theResourceName)) {
bool.must(qb.keyword().onField("myResourceType").matching(theResourceName).createQuery());
}
-
+//
//@formatter:off
+ String value = nextTokenParam.getValue().toLowerCase();
Query textQuery = qb
.phrase()
.withSlop(2)
.onField("myValueText").boostedTo(4.0f)
.andField("myValueTextEdgeNGram").boostedTo(2.0f)
- .andField("myValueTextNGram").boostedTo(1.0f)
- .sentence(nextTokenParam.getValue().toLowerCase()).createQuery();
+// .andField("myValueTextNGram").boostedTo(1.0f)
+ .sentence(value).createQuery();
bool.must(textQuery);
//@formatter:on
- FullTextQuery ftq = em.createFullTextQuery(bool.createQuery(), ResourceTable.class);
- ftq.setProjection("myResourcePid");
+ FullTextQuery ftq = em.createFullTextQuery(bool.createQuery(), ResourceIndexedSearchParamString.class);
List> resultList = ftq.getResultList();
pids = new ArrayList();
for (Object next : resultList) {
- Object[] nextAsArray = (Object[]) next;
- Long nextValue = (Long) nextAsArray[0];
- pids.add(nextValue);
+ ResourceIndexedSearchParamString nextAsArray = (ResourceIndexedSearchParamString) next;
+ pids.add(nextAsArray.getResourcePid());
}
}
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/BaseResourceIndexedSearchParam.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/BaseResourceIndexedSearchParam.java
index 43c5333ac96..65fae6bcd4d 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/BaseResourceIndexedSearchParam.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/BaseResourceIndexedSearchParam.java
@@ -47,20 +47,19 @@ public abstract class BaseResourceIndexedSearchParam implements Serializable {
private Long myId;
@Field
- @Column(name = "SP_NAME", length = MAX_SP_NAME, nullable=false)
+ @Column(name = "SP_NAME", length = MAX_SP_NAME, nullable = false)
private String myParamName;
@ManyToOne(optional = false)
- @JoinColumn(name = "RES_ID", referencedColumnName="RES_ID")
+ @JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID")
@ContainedIn
private ResourceTable myResource;
- @Field(store=Store.YES)
@Column(name = "RES_ID", insertable = false, updatable = false)
private Long myResourcePid;
- @Field(store=Store.YES)
- @Column(name = "RES_TYPE", nullable=false)
+ @Field()
+ @Column(name = "RES_TYPE", nullable = false)
private String myResourceType;
protected Long getId() {
@@ -75,6 +74,10 @@ public abstract class BaseResourceIndexedSearchParam implements Serializable {
return myResource;
}
+ public Long getResourcePid() {
+ return myResourcePid;
+ }
+
public void setParamName(String theName) {
myParamName = theName;
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamString.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamString.java
index 1a8f7cf6f05..2d22e997330 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamString.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamString.java
@@ -201,4 +201,5 @@ public class ResourceIndexedSearchParamString extends BaseResourceIndexedSearchP
b.append("value", getValueNormalized());
return b.build();
}
+
}
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/BaseJpaDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/BaseJpaDstu2Test.java
index f9d53358aab..1149b1548d4 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/BaseJpaDstu2Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/BaseJpaDstu2Test.java
@@ -191,6 +191,7 @@ public abstract class BaseJpaDstu2Test extends BaseJpaTest {
public void beforeFlushFT() {
FullTextEntityManager ftem = Search.getFullTextEntityManager(myEntityManager);
ftem.purgeAll(ResourceTable.class);
+ ftem.purgeAll(ResourceIndexedSearchParamString.class);
ftem.flushToIndexes();
myDaoConfig.setSchedulingDisabled(true);
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu21/BaseJpaDstu21Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu21/BaseJpaDstu21Test.java
index f7b93f3d247..33c7e19a1f7 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu21/BaseJpaDstu21Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu21/BaseJpaDstu21Test.java
@@ -185,6 +185,7 @@ public abstract class BaseJpaDstu21Test extends BaseJpaTest {
public void beforeFlushFT() {
FullTextEntityManager ftem = Search.getFullTextEntityManager(myEntityManager);
ftem.purgeAll(ResourceTable.class);
+ ftem.purgeAll(ResourceIndexedSearchParamString.class);
ftem.flushToIndexes();
myDaoConfig.setSchedulingDisabled(true);
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu21/FhirResourceDaoDstu21SearchFtTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu21/FhirResourceDaoDstu21SearchFtTest.java
index 51a975d1131..b704eebf41a 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu21/FhirResourceDaoDstu21SearchFtTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu21/FhirResourceDaoDstu21SearchFtTest.java
@@ -38,12 +38,12 @@ public class FhirResourceDaoDstu21SearchFtTest extends BaseJpaDstu21Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu21SearchFtTest.class);
@Test
- @Ignore
public void testCodeTextSearch() {
Observation obs1 = new Observation();
obs1.getCode().setText("Systolic Blood Pressure");
obs1.setStatus(ObservationStatusEnum.FINAL);
obs1.setValue(new QuantityDt(123));
+ obs1.setComments("obs1");
IIdType id1 = myObservationDao.create(obs1).getId().toUnqualifiedVersionless();
Observation obs2 = new Observation();
@@ -55,10 +55,43 @@ public class FhirResourceDaoDstu21SearchFtTest extends BaseJpaDstu21Test {
SearchParameterMap map;
map = new SearchParameterMap();
- map.add(Observation.SP_CODE, new TokenParam(null, "Systolic").setText(true));
- assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), containsInAnyOrder(id1, id2));
-
+ map.add(Observation.SP_CODE, new TokenParam(null, "blood").setText(true));
+ assertThat(toUnqualifiedVersionlessIds(myObservationDao.search(map)), containsInAnyOrder(id1, id2));
+
+ map = new SearchParameterMap();
+ map.add(Observation.SP_CODE, new TokenParam(null, "blood").setText(true));
+ assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), empty());
+
+ map = new SearchParameterMap();
+ map.add(Observation.SP_CODE, new TokenParam(null, "blood").setText(true));
+ map.add(Constants.PARAM_CONTENT, new StringParam("obs1"));
+ assertThat(toUnqualifiedVersionlessIds(myObservationDao.search(map)), containsInAnyOrder(id1));
+
}
+
+ @Test
+ @Ignore
+ public void testStringTextSearch() {
+ Observation obs1 = new Observation();
+ obs1.getCode().setText("AAAAA");
+ obs1.setValue(new StringDt("Systolic Blood Pressure"));
+ obs1.setStatus(ObservationStatusEnum.FINAL);
+ IIdType id1 = myObservationDao.create(obs1).getId().toUnqualifiedVersionless();
+
+ Observation obs2 = new Observation();
+ obs1.getCode().setText("AAAAA");
+ obs1.setValue(new StringDt("Diastolic Blood Pressure"));
+ obs2.setStatus(ObservationStatusEnum.FINAL);
+ IIdType id2 = myObservationDao.create(obs2).getId().toUnqualifiedVersionless();
+
+ SearchParameterMap map;
+
+ map = new SearchParameterMap();
+ map.add(Observation.SP_VALUE_STRING, new StringParam("sure").setContains(true));
+ assertThat(toUnqualifiedVersionlessIds(myObservationDao.search(map)), containsInAnyOrder(id1, id2));
+
+ }
+
@Test
public void testSuggestIgnoresBase64Content() {
diff --git a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/StringParameterTest.java b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/StringParameterTest.java
index 9e26d5be165..d64e462b0b4 100644
--- a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/StringParameterTest.java
+++ b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/server/StringParameterTest.java
@@ -36,6 +36,18 @@ public class StringParameterTest {
private static Server ourServer;
+ @Test
+ public void testContains() {
+ StringParam sp = new StringParam("VAL");
+ sp.setContains(true);
+ assertEquals(":contains", sp.getQueryParameterQualifier());
+
+ sp = new StringParam("VAL");
+ sp.setValueAsQueryToken(":contains", "VAL");
+ assertEquals(true, sp.isContains());
+ assertEquals("VAL", sp.getValue());
+ }
+
@Test
public void testRawString() throws Exception {
{
diff --git a/pom.xml b/pom.xml
index 4cb5894c9f8..ad590bd4675 100644
--- a/pom.xml
+++ b/pom.xml
@@ -742,7 +742,7 @@
true
random
-Dfile.encoding=UTF-8
- false
+