Start work on FT search
This commit is contained in:
parent
0958ab6f16
commit
8e8db1801c
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,11 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
|
||||
public interface ISearchDao {
|
||||
|
||||
public static final String FULL_TEXT_PARAM_NAME = "fullTextSearch";
|
||||
|
||||
IBundleProvider search(SearchParameterMap theParams);
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.PersistenceContextType;
|
||||
|
||||
import org.hibernate.search.jpa.FullTextEntityManager;
|
||||
import org.hibernate.search.jpa.FullTextQuery;
|
||||
import org.hibernate.search.query.dsl.QueryBuilder;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
|
||||
public class SearchDao extends BaseHapiFhirDao<IBaseResource> implements ISearchDao {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchDao.class);
|
||||
|
||||
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
|
||||
private EntityManager myEntityManager;
|
||||
|
||||
@Transactional()
|
||||
@Override
|
||||
public IBundleProvider search(SearchParameterMap theParams) {
|
||||
|
||||
FullTextEntityManager em = org.hibernate.search.jpa.Search.getFullTextEntityManager(myEntityManager);
|
||||
|
||||
for (String nextParamName : theParams.keySet()) {
|
||||
if (nextParamName.equals(FULL_TEXT_PARAM_NAME)) {
|
||||
QueryBuilder qb = em.getSearchFactory().buildQueryBuilder().forEntity(ResourceIndexedSearchParamString.class).get();
|
||||
org.apache.lucene.search.Query luceneQuery = qb
|
||||
.keyword()
|
||||
.onFields("myValueComplete")
|
||||
.matching("AAAS")
|
||||
.createQuery();
|
||||
|
||||
// wrap Lucene query in a javax.persistence.Query
|
||||
FullTextQuery jpaQuery = em.createFullTextQuery(luceneQuery, ResourceIndexedSearchParamString.class);
|
||||
|
||||
// execute search
|
||||
List<?> result = jpaQuery.getResultList();
|
||||
for (Object object : result) {
|
||||
ourLog.info(""+ object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -46,7 +46,6 @@ public class SearchParameterMap extends LinkedHashMap<String, List<List<? extend
|
|||
private Set<Include> myIncludes;
|
||||
private DateRangeParam myLastUpdated;
|
||||
private Set<Include> myRevIncludes;
|
||||
|
||||
private SortSpec mySort;
|
||||
|
||||
public void add(String theName, IQueryParameterAnd<?> theAnd) {
|
||||
|
|
|
@ -30,6 +30,8 @@ import javax.persistence.JoinColumn;
|
|||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
|
||||
import org.hibernate.search.annotations.Field;
|
||||
|
||||
@MappedSuperclass
|
||||
public abstract class BaseResourceIndexedSearchParam implements Serializable {
|
||||
|
||||
|
@ -42,6 +44,7 @@ public abstract class BaseResourceIndexedSearchParam implements Serializable {
|
|||
@Column(name = "SP_ID")
|
||||
private Long myId;
|
||||
|
||||
@Field
|
||||
@Column(name = "SP_NAME", length = MAX_SP_NAME, nullable=false)
|
||||
private String myParamName;
|
||||
|
||||
|
@ -49,9 +52,11 @@ public abstract class BaseResourceIndexedSearchParam implements Serializable {
|
|||
@JoinColumn(name = "RES_ID", referencedColumnName="RES_ID")
|
||||
private ResourceTable myResource;
|
||||
|
||||
@Field
|
||||
@Column(name = "RES_ID", insertable = false, updatable = false)
|
||||
private Long myResourcePid;
|
||||
|
||||
@Field
|
||||
@Column(name = "RES_TYPE", nullable=false)
|
||||
private String myResourceType;
|
||||
|
||||
|
|
|
@ -28,8 +28,11 @@ 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.search.annotations.Field;
|
||||
import org.hibernate.search.annotations.Indexed;
|
||||
|
||||
//@formatter:off
|
||||
@Indexed
|
||||
@Entity
|
||||
@Table(name = "HFJ_SPIDX_COORDS" /* , indexes = { @Index(name = "IDX_SP_TOKEN", columnList = "SP_SYSTEM,SP_VALUE") } */)
|
||||
@org.hibernate.annotations.Table(appliesTo = "HFJ_SPIDX_COORDS", indexes = {
|
||||
|
@ -43,9 +46,11 @@ public class ResourceIndexedSearchParamCoords extends BaseResourceIndexedSearchP
|
|||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Column(name = "SP_LATITUDE")
|
||||
@Field
|
||||
public double myLatitude;
|
||||
|
||||
@Column(name = "SP_LONGITUDE")
|
||||
@Field
|
||||
public double myLongitude;
|
||||
|
||||
public ResourceIndexedSearchParamCoords() {
|
||||
|
|
|
@ -32,8 +32,11 @@ 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.search.annotations.Field;
|
||||
import org.hibernate.search.annotations.Indexed;
|
||||
|
||||
//@formatter:off
|
||||
@Indexed
|
||||
@Entity
|
||||
@Table(name = "HFJ_SPIDX_DATE" /*, indexes= {@Index(name="IDX_SP_DATE", columnList= "SP_VALUE_LOW,SP_VALUE_HIGH")}*/)
|
||||
@org.hibernate.annotations.Table(appliesTo = "HFJ_SPIDX_DATE", indexes= {
|
||||
|
@ -46,15 +49,23 @@ public class ResourceIndexedSearchParamDate extends BaseResourceIndexedSearchPar
|
|||
|
||||
@Column(name = "SP_VALUE_HIGH", nullable = true)
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@Field
|
||||
public Date myValueHigh;
|
||||
|
||||
@Column(name = "SP_VALUE_LOW", nullable = true)
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@Field
|
||||
public Date myValueLow;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ResourceIndexedSearchParamDate() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ResourceIndexedSearchParamDate(String theName, Date theLow, Date theHigh) {
|
||||
setParamName(theName);
|
||||
setValueLow(theLow);
|
||||
|
|
|
@ -30,8 +30,11 @@ 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.search.annotations.Field;
|
||||
import org.hibernate.search.annotations.Indexed;
|
||||
|
||||
//@formatter:off
|
||||
@Indexed
|
||||
@Entity
|
||||
@Table(name = "HFJ_SPIDX_NUMBER" /*, indexes= {@Index(name="IDX_SP_NUMBER", columnList="SP_VALUE")}*/ )
|
||||
@org.hibernate.annotations.Table(appliesTo = "HFJ_SPIDX_NUMBER", indexes= {
|
||||
|
@ -43,6 +46,7 @@ public class ResourceIndexedSearchParamNumber extends BaseResourceIndexedSearchP
|
|||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Column(name = "SP_VALUE", nullable = true)
|
||||
@Field
|
||||
public BigDecimal myValue;
|
||||
|
||||
public ResourceIndexedSearchParamNumber() {
|
||||
|
|
|
@ -30,8 +30,11 @@ 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.search.annotations.Field;
|
||||
import org.hibernate.search.annotations.Indexed;
|
||||
|
||||
//@formatter:off
|
||||
@Indexed
|
||||
@Entity
|
||||
@Table(name = "HFJ_SPIDX_QUANTITY" /*, indexes= {@Index(name="IDX_SP_NUMBER", columnList="SP_VALUE")}*/ )
|
||||
@org.hibernate.annotations.Table(appliesTo = "HFJ_SPIDX_QUANTITY", indexes= {
|
||||
|
@ -40,15 +43,20 @@ import org.apache.commons.lang3.builder.ToStringStyle;
|
|||
//@formatter:on
|
||||
public class ResourceIndexedSearchParamQuantity extends BaseResourceIndexedSearchParam {
|
||||
|
||||
private static final int MAX_LENGTH = 200;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Column(name = "SP_SYSTEM", nullable = true, length = 100)
|
||||
@Column(name = "SP_SYSTEM", nullable = true, length = MAX_LENGTH)
|
||||
@Field
|
||||
public String mySystem;
|
||||
|
||||
@Column(name = "SP_UNITS", nullable = true, length = 100)
|
||||
@Column(name = "SP_UNITS", nullable = true, length = MAX_LENGTH)
|
||||
@Field
|
||||
public String myUnits;
|
||||
|
||||
@Column(name = "SP_VALUE", nullable = true)
|
||||
@Field
|
||||
public BigDecimal myValue;
|
||||
|
||||
public ResourceIndexedSearchParamQuantity() {
|
||||
|
|
|
@ -29,7 +29,10 @@ 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.search.annotations.Field;
|
||||
import org.hibernate.search.annotations.Indexed;
|
||||
|
||||
@Indexed
|
||||
@Entity
|
||||
@Table(name = "HFJ_SPIDX_STRING"/* , indexes= {@Index(name="IDX_SP_STRING", columnList="SP_VALUE_NORMALIZED")} */)
|
||||
@org.hibernate.annotations.Table(appliesTo = "HFJ_SPIDX_STRING", indexes = {
|
||||
|
@ -37,16 +40,20 @@ import org.apache.commons.lang3.builder.ToStringStyle;
|
|||
})
|
||||
public class ResourceIndexedSearchParamString extends BaseResourceIndexedSearchParam {
|
||||
|
||||
public static final int MAX_LENGTH = 100;
|
||||
public static final int MAX_LENGTH = 200;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Column(name = "SP_VALUE_EXACT", length = 100, nullable = true)
|
||||
public String myValueExact;
|
||||
@Column(name = "SP_VALUE_EXACT", length = MAX_LENGTH, nullable = true)
|
||||
private String myValueExact;
|
||||
|
||||
@Column(name = "SP_VALUE_NORMALIZED", length = MAX_LENGTH, nullable = true)
|
||||
public String myValueNormalized;
|
||||
private String myValueNormalized;
|
||||
|
||||
@Column(name="SP_VALUE_EXACT", insertable=false, updatable=false)
|
||||
@Field
|
||||
private String myValueComplete;
|
||||
|
||||
public ResourceIndexedSearchParamString() {
|
||||
}
|
||||
|
||||
|
@ -97,6 +104,7 @@ public class ResourceIndexedSearchParamString extends BaseResourceIndexedSearchP
|
|||
throw new IllegalArgumentException("Value is too long: " + theValueExact.length());
|
||||
}
|
||||
myValueExact = theValueExact;
|
||||
myValueComplete = theValueExact;
|
||||
}
|
||||
|
||||
public void setValueNormalized(String theValueNormalized) {
|
||||
|
|
|
@ -29,21 +29,26 @@ 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.search.annotations.Field;
|
||||
import org.hibernate.search.annotations.Indexed;
|
||||
|
||||
@Indexed
|
||||
@Entity
|
||||
@Table(name = "HFJ_SPIDX_TOKEN" /* , indexes = { @Index(name = "IDX_SP_TOKEN", columnList = "SP_SYSTEM,SP_VALUE") } */)
|
||||
@org.hibernate.annotations.Table(appliesTo = "HFJ_SPIDX_TOKEN", indexes = { @org.hibernate.annotations.Index(name = "IDX_SP_TOKEN", columnNames = { "RES_TYPE", "SP_NAME", "SP_SYSTEM", "SP_VALUE" }),
|
||||
@org.hibernate.annotations.Index(name = "IDX_SP_TOKEN_UNQUAL", columnNames = { "RES_TYPE", "SP_NAME", "SP_VALUE" }) })
|
||||
public class ResourceIndexedSearchParamToken extends BaseResourceIndexedSearchParam {
|
||||
|
||||
public static final int MAX_LENGTH = 100;
|
||||
public static final int MAX_LENGTH = 200;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Field()
|
||||
@Column(name = "SP_SYSTEM", nullable = true, length = MAX_LENGTH)
|
||||
public String mySystem;
|
||||
|
||||
@Column(name = "SP_VALUE", nullable = true, length = 100)
|
||||
@Field()
|
||||
@Column(name = "SP_VALUE", nullable = true, length = MAX_LENGTH)
|
||||
public String myValue;
|
||||
|
||||
public ResourceIndexedSearchParamToken() {
|
||||
|
|
|
@ -28,8 +28,12 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.hibernate.search.annotations.Analyzer;
|
||||
import org.hibernate.search.annotations.Field;
|
||||
import org.hibernate.search.annotations.Indexed;
|
||||
|
||||
//@formatter:off
|
||||
@Indexed
|
||||
@Entity
|
||||
@Table(name = "HFJ_SPIDX_URI" /* , indexes = { @Index(name = "IDX_SP_TOKEN", columnList = "SP_SYSTEM,SP_VALUE") } */)
|
||||
@org.hibernate.annotations.Table(appliesTo = "HFJ_SPIDX_URI", indexes = {
|
||||
|
@ -43,6 +47,7 @@ public class ResourceIndexedSearchParamUri extends BaseResourceIndexedSearchPara
|
|||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Column(name = "SP_URI", nullable = true, length = MAX_LENGTH)
|
||||
@Field()
|
||||
public String myUri;
|
||||
|
||||
public ResourceIndexedSearchParamUri() {
|
||||
|
|
|
@ -34,28 +34,22 @@ import javax.persistence.FetchType;
|
|||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.annotations.Index;
|
||||
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
|
||||
//@formatter:off
|
||||
@Entity
|
||||
@Table(name = "HFJ_RESOURCE", uniqueConstraints = {})
|
||||
@Inheritance(strategy = InheritanceType.JOINED)
|
||||
@org.hibernate.annotations.Table(appliesTo = "HFJ_RESOURCE",
|
||||
indexes = {
|
||||
@Index(name = "IDX_RES_DATE", columnNames = { "RES_UPDATED" }),
|
||||
@Index(name = "IDX_RES_LANG", columnNames = { "RES_TYPE", "RES_LANGUAGE" }),
|
||||
@Index(name = "IDX_RES_PROFILE", columnNames = { "RES_PROFILE" }),
|
||||
@Index(name = "IDX_INDEXSTATUS", columnNames = { "SP_INDEX_STATUS" })
|
||||
})
|
||||
@Table(name = "HFJ_RESOURCE", uniqueConstraints = {}, indexes= {
|
||||
@Index(name = "IDX_RES_DATE", columnList="RES_UPDATED"),
|
||||
@Index(name = "IDX_RES_LANG", columnList="RES_TYPE,RES_LANGUAGE"),
|
||||
@Index(name = "IDX_RES_PROFILE", columnList="RES_PROFILE"),
|
||||
@Index(name = "IDX_INDEXSTATUS", columnList="SP_INDEX_STATUS")
|
||||
})
|
||||
//@formatter:on
|
||||
public class ResourceTable extends BaseHasResource implements Serializable {
|
||||
private static final int MAX_LANGUAGE_LENGTH = 20;
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<beans
|
||||
xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:websocket="http://www.springframework.org/schema/websocket"
|
||||
xmlns:task="http://www.springframework.org/schema/task"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
|
||||
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
|
||||
|
||||
<context:annotation-config />
|
||||
|
||||
<tx:annotation-driven transaction-manager="myTxManagerDstu2" />
|
||||
|
||||
<bean id="mySearchDaoDstu2" class="ca.uhn.fhir.jpa.dao.SearchDao" />
|
||||
|
||||
</beans>
|
|
@ -0,0 +1,39 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.rest.param.StringAndListParam;
|
||||
import ca.uhn.fhir.rest.param.StringOrListParam;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
|
||||
@ContextConfiguration(locations = { "classpath:fhir-spring-search-config-dstu2.xml" })
|
||||
public class FhirSearchDaoDstu2Test extends BaseJpaDstu2Test {
|
||||
|
||||
@Autowired
|
||||
private ISearchDao mySearchDao;
|
||||
|
||||
@Test
|
||||
public void testStringSearch() {
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
patient.addName().addGiven("testSearchStringParamWithNonNormalized_h\u00F6ra");
|
||||
patient.addName().addFamily("AAAS");
|
||||
myPatientDao.create(patient);
|
||||
}
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
patient.addName().addGiven("testSearchStringParamWithNonNormalized_HORA");
|
||||
myPatientDao.create(patient);
|
||||
}
|
||||
|
||||
SearchParameterMap map = new SearchParameterMap();
|
||||
map.add(ISearchDao.FULL_TEXT_PARAM_NAME, new StringAndListParam().addAnd(new StringOrListParam().addOr(new StringParam("AAA"))));
|
||||
mySearchDao.search(map);
|
||||
}
|
||||
|
||||
}
|
|
@ -35,6 +35,9 @@
|
|||
<property name="hibernate.cache.use_query_cache" value="false" />
|
||||
<property name="hibernate.cache.use_second_level_cache" value="false" />
|
||||
<property name="hibernate.cache.use_structured_entries" value="false" />
|
||||
<property name="hibernate.search.default.directory_provider" value="filesystem"/>
|
||||
<property name="hibernate.search.default.indexBase" value="./lucene_indexes"/>
|
||||
|
||||
<!--
|
||||
<property name="hibernate.ejb.naming_strategy" value="ca.uhn.fhir.jpa.util.CustomNamingStrategy" />
|
||||
-->
|
||||
|
|
Loading…
Reference in New Issue