DATAES-17 : Add support to retrieve highlighted text in search result

This commit is contained in:
Mohsin Husen 2013-08-07 10:15:06 +01:00
parent 096c2e197e
commit 99a30a2a4b
6 changed files with 93 additions and 4 deletions

View File

@ -40,6 +40,7 @@ import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.facet.Facet; import org.elasticsearch.search.facet.Facet;
import org.elasticsearch.search.facet.FacetBuilder; import org.elasticsearch.search.facet.FacetBuilder;
import org.elasticsearch.search.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder; import org.elasticsearch.search.sort.SortOrder;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
@ -388,6 +389,12 @@ public class ElasticsearchTemplate implements ElasticsearchOperations {
} }
} }
if(searchQuery.getHighlightFields() != null) {
for(HighlightBuilder.Field highlightField : searchQuery.getHighlightFields()){
searchRequest.addHighlightedField(highlightField);
}
}
return searchRequest.setQuery(searchQuery.getQuery()).execute().actionGet(); return searchRequest.setQuery(searchQuery.getQuery()).execute().actionGet();
} }

View File

@ -17,7 +17,7 @@ package org.springframework.data.elasticsearch.core.query;
import org.elasticsearch.index.query.FilterBuilder; import org.elasticsearch.index.query.FilterBuilder;
import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.facet.FacetBuilder; import org.elasticsearch.search.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilder; import org.elasticsearch.search.sort.SortBuilder;
import org.springframework.data.elasticsearch.core.facet.FacetRequest; import org.springframework.data.elasticsearch.core.facet.FacetRequest;
@ -37,6 +37,7 @@ public class NativeSearchQuery extends AbstractQuery implements SearchQuery {
private FilterBuilder filter; private FilterBuilder filter;
private SortBuilder sort; private SortBuilder sort;
private List<FacetRequest> facets; private List<FacetRequest> facets;
private HighlightBuilder.Field[] highlightFields;
public NativeSearchQuery(QueryBuilder query) { public NativeSearchQuery(QueryBuilder query) {
@ -54,6 +55,13 @@ public class NativeSearchQuery extends AbstractQuery implements SearchQuery {
this.sort = sort; this.sort = sort;
} }
public NativeSearchQuery(QueryBuilder query, FilterBuilder filter, SortBuilder sort, HighlightBuilder.Field[] highlightFields) {
this.query = query;
this.filter = filter;
this.sort = sort;
this.highlightFields = highlightFields;
}
public QueryBuilder getQuery() { public QueryBuilder getQuery() {
return query; return query;
} }
@ -64,6 +72,11 @@ public class NativeSearchQuery extends AbstractQuery implements SearchQuery {
public SortBuilder getElasticsearchSort() { public SortBuilder getElasticsearchSort() {
return sort; return sort;
}
@Override
public HighlightBuilder.Field[] getHighlightFields() {
return highlightFields;
} }
public void addFacet(FacetRequest facetRequest){ public void addFacet(FacetRequest facetRequest){

View File

@ -18,6 +18,7 @@ package org.springframework.data.elasticsearch.core.query;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.elasticsearch.index.query.FilterBuilder; import org.elasticsearch.index.query.FilterBuilder;
import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilder; import org.elasticsearch.search.sort.SortBuilder;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.facet.FacetRequest; import org.springframework.data.elasticsearch.core.facet.FacetRequest;
@ -39,6 +40,7 @@ public class NativeSearchQueryBuilder {
private FilterBuilder filterBuilder; private FilterBuilder filterBuilder;
private SortBuilder sortBuilder; private SortBuilder sortBuilder;
private List<FacetRequest> facetRequests = new ArrayList<FacetRequest>(); private List<FacetRequest> facetRequests = new ArrayList<FacetRequest>();
private HighlightBuilder.Field[] highlightFields;
private Pageable pageable; private Pageable pageable;
private String[] indices; private String[] indices;
private String[] types; private String[] types;
@ -64,6 +66,11 @@ public class NativeSearchQueryBuilder {
return this; return this;
} }
public NativeSearchQueryBuilder withHighlightFields(HighlightBuilder.Field... highlightFields){
this.highlightFields = highlightFields;
return this;
}
public NativeSearchQueryBuilder withPageable(Pageable pageable) { public NativeSearchQueryBuilder withPageable(Pageable pageable) {
this.pageable = pageable; this.pageable = pageable;
return this; return this;
@ -85,7 +92,7 @@ public class NativeSearchQueryBuilder {
} }
public NativeSearchQuery build() { public NativeSearchQuery build() {
NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(queryBuilder, filterBuilder, sortBuilder); NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(queryBuilder, filterBuilder, sortBuilder, highlightFields);
if (pageable != null) { if (pageable != null) {
nativeSearchQuery.setPageable(pageable); nativeSearchQuery.setPageable(pageable);
} }

View File

@ -17,7 +17,7 @@ package org.springframework.data.elasticsearch.core.query;
import org.elasticsearch.index.query.FilterBuilder; import org.elasticsearch.index.query.FilterBuilder;
import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.facet.FacetBuilder; import org.elasticsearch.search.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilder; import org.elasticsearch.search.sort.SortBuilder;
import org.springframework.data.elasticsearch.core.facet.FacetRequest; import org.springframework.data.elasticsearch.core.facet.FacetRequest;
@ -38,4 +38,6 @@ public interface SearchQuery extends Query {
SortBuilder getElasticsearchSort(); SortBuilder getElasticsearchSort();
List<FacetRequest> getFacets(); List<FacetRequest> getFacets();
HighlightBuilder.Field[] getHighlightFields();
} }

View File

@ -34,6 +34,7 @@ public class SampleEntity {
private String message; private String message;
private int rate; private int rate;
private boolean available; private boolean available;
private String highlightedMessage;
@Version @Version
private Long version; private Long version;
@ -77,6 +78,14 @@ public class SampleEntity {
this.available = available; this.available = available;
} }
public String getHighlightedMessage() {
return highlightedMessage;
}
public void setHighlightedMessage(String highlightedMessage) {
this.highlightedMessage = highlightedMessage;
}
public Long getVersion() { public Long getVersion() {
return version; return version;
} }

View File

@ -19,6 +19,7 @@ import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.engine.DocumentMissingException; import org.elasticsearch.index.engine.DocumentMissingException;
import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder; import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder; import org.elasticsearch.search.sort.SortOrder;
import org.junit.Before; import org.junit.Before;
@ -27,7 +28,6 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.SampleEntity; import org.springframework.data.elasticsearch.SampleEntity;
@ -44,6 +44,7 @@ import static org.elasticsearch.index.query.FilterBuilders.boolFilter;
import static org.elasticsearch.index.query.FilterBuilders.termFilter; import static org.elasticsearch.index.query.FilterBuilders.termFilter;
import static org.elasticsearch.index.query.QueryBuilders.fieldQuery; import static org.elasticsearch.index.query.QueryBuilders.fieldQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
@ -778,4 +779,54 @@ public class ElasticsearchTemplateTests {
assertThat(indexedEntity.getMessage(), is(message)); assertThat(indexedEntity.getMessage(), is(message));
} }
@Test
public void shouldReturnHighlightedFieldsForGivenQueryAndFields(){
//given
String documentId = randomNumeric(5);
String actualMessage = "some test message";
String highlightedMessage = "some <em>test</em> message";
SampleEntity sampleEntity = new SampleEntity();
sampleEntity.setId(documentId);
sampleEntity.setMessage(actualMessage);
sampleEntity.setVersion(System.currentTimeMillis());
IndexQuery indexQuery = new IndexQuery();
indexQuery.setId(documentId);
indexQuery.setObject(sampleEntity);
elasticsearchTemplate.index(indexQuery);
elasticsearchTemplate.refresh(SampleEntity.class, true);
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(termQuery("message", "test"))
.withHighlightFields(new HighlightBuilder.Field("message"))
.build();
Page<SampleEntity> sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, new ResultsMapper<SampleEntity>() {
@Override
public FacetedPage<SampleEntity> mapResults(SearchResponse response) {
List<SampleEntity> chunk = new ArrayList<SampleEntity>();
for (SearchHit searchHit : response.getHits()) {
if (response.getHits().getHits().length <= 0) {
return null;
}
SampleEntity user = new SampleEntity();
user.setId(searchHit.getId());
user.setMessage((String) searchHit.getSource().get("message"));
user.setHighlightedMessage(searchHit.getHighlightFields().get("message").fragments()[0].toString());
chunk.add(user);
}
if(chunk.size() > 0){
return new FacetedPageImpl<SampleEntity>(chunk);
}
return null;
}
});
assertThat(sampleEntities.getContent().get(0).getHighlightedMessage(), is(highlightedMessage));
}
} }