mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-05-31 01:02:12 +00:00
DATAES-593 - Add support for field collapse function.
Original PR: #290
This commit is contained in:
parent
f1aa75a94f
commit
0d1c57a874
@ -137,6 +137,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
* @author Lorenzo Spinelli
|
||||
* @author Dmitriy Yakovlev
|
||||
* @author Roman Puchkovskiy
|
||||
* @author Martin Choraine
|
||||
* @author Farid Azaza
|
||||
*/
|
||||
public class ElasticsearchRestTemplate
|
||||
@ -1101,6 +1102,10 @@ public class ElasticsearchRestTemplate
|
||||
}
|
||||
}
|
||||
|
||||
if (searchQuery.getCollapseBuilder() != null) {
|
||||
searchRequest.source().collapse(searchQuery.getCollapseBuilder());
|
||||
}
|
||||
|
||||
if (searchQuery.getHighlightFields() != null || searchQuery.getHighlightBuilder() != null) {
|
||||
HighlightBuilder highlightBuilder = searchQuery.getHighlightBuilder();
|
||||
if (highlightBuilder == null) {
|
||||
|
@ -120,6 +120,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Christoph Strobl
|
||||
* @author Dmitriy Yakovlev
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Martin Choraine
|
||||
* @author Farid Azaza
|
||||
*/
|
||||
public class ElasticsearchTemplate implements ElasticsearchOperations, EsClient<Client>, ApplicationContextAware {
|
||||
@ -922,6 +923,10 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, EsClient<
|
||||
}
|
||||
}
|
||||
|
||||
if (searchQuery.getCollapseBuilder() != null) {
|
||||
searchRequest.setCollapse(searchQuery.getCollapseBuilder());
|
||||
}
|
||||
|
||||
if (searchQuery.getHighlightFields() != null || searchQuery.getHighlightBuilder() != null) {
|
||||
HighlightBuilder highlightBuilder = searchQuery.getHighlightBuilder();
|
||||
if (highlightBuilder == null) {
|
||||
@ -952,6 +957,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, EsClient<
|
||||
searchRequest.addAggregation(aggregatedFacet.getFacet());
|
||||
}
|
||||
}
|
||||
|
||||
return searchRequest.setQuery(searchQuery.getQuery());
|
||||
}
|
||||
|
||||
|
@ -76,6 +76,7 @@ import org.springframework.util.Assert;
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @author Farid Azaza
|
||||
* @author Martin Choraine
|
||||
* @since 3.2
|
||||
*/
|
||||
public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOperations {
|
||||
@ -263,6 +264,10 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera
|
||||
searchSourceBuilder.fetchSource(query.getSourceFilter().getIncludes(), query.getSourceFilter().getExcludes());
|
||||
}
|
||||
|
||||
if (query instanceof NativeSearchQuery && ((NativeSearchQuery) query).getCollapseBuilder() != null) {
|
||||
searchSourceBuilder.collapse(((NativeSearchQuery) query).getCollapseBuilder());
|
||||
}
|
||||
|
||||
sort(query, entity).forEach(searchSourceBuilder::sort);
|
||||
|
||||
if (query.getMinScore() > 0) {
|
||||
|
@ -20,6 +20,7 @@ import java.util.List;
|
||||
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
||||
import org.elasticsearch.search.collapse.CollapseBuilder;
|
||||
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
|
||||
import org.elasticsearch.search.sort.SortBuilder;
|
||||
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
|
||||
@ -33,20 +34,21 @@ import java.util.Arrays;
|
||||
* @author Mohsin Husen
|
||||
* @author Artur Konczak
|
||||
* @author Jean-Baptiste Nizet
|
||||
* @author Martin Choraine
|
||||
*/
|
||||
public class NativeSearchQuery extends AbstractQuery implements SearchQuery {
|
||||
|
||||
private QueryBuilder query;
|
||||
private QueryBuilder filter;
|
||||
private List<SortBuilder> sorts;
|
||||
private final List<ScriptField> scriptFields = new ArrayList<>();
|
||||
private final List<ScriptField> scriptFields = new ArrayList<>();
|
||||
private CollapseBuilder collapseBuilder;
|
||||
private List<FacetRequest> facets;
|
||||
private List<AbstractAggregationBuilder> aggregations;
|
||||
private HighlightBuilder highlightBuilder;
|
||||
private HighlightBuilder.Field[] highlightFields;
|
||||
private List<IndexBoost> indicesBoost;
|
||||
|
||||
|
||||
public NativeSearchQuery(QueryBuilder query) {
|
||||
this.query = query;
|
||||
}
|
||||
@ -111,6 +113,15 @@ public class NativeSearchQuery extends AbstractQuery implements SearchQuery {
|
||||
scriptFields.addAll(Arrays.asList(scriptField));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollapseBuilder getCollapseBuilder() {
|
||||
return collapseBuilder;
|
||||
}
|
||||
|
||||
public void setCollapseBuilder(CollapseBuilder collapseBuilder) {
|
||||
this.collapseBuilder = collapseBuilder;
|
||||
}
|
||||
|
||||
public void addFacet(FacetRequest facetRequest) {
|
||||
if (facets == null) {
|
||||
facets = new ArrayList<>();
|
||||
@ -132,7 +143,6 @@ public class NativeSearchQuery extends AbstractQuery implements SearchQuery {
|
||||
return aggregations;
|
||||
}
|
||||
|
||||
|
||||
public void addAggregation(AbstractAggregationBuilder aggregationBuilder) {
|
||||
if (aggregations == null) {
|
||||
aggregations = new ArrayList<>();
|
||||
|
@ -25,6 +25,7 @@ import org.elasticsearch.action.search.SearchType;
|
||||
import org.elasticsearch.action.support.IndicesOptions;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
||||
import org.elasticsearch.search.collapse.CollapseBuilder;
|
||||
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
|
||||
import org.elasticsearch.search.sort.SortBuilder;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@ -40,6 +41,7 @@ import org.springframework.data.elasticsearch.core.facet.FacetRequest;
|
||||
* @author Alen Turkovic
|
||||
* @author Sascha Woo
|
||||
* @author Jean-Baptiste Nizet
|
||||
* @author Martin Choraine
|
||||
* @author Farid Azaza
|
||||
*/
|
||||
public class NativeSearchQueryBuilder {
|
||||
@ -57,6 +59,7 @@ public class NativeSearchQueryBuilder {
|
||||
private String[] types;
|
||||
private String[] fields;
|
||||
private SourceFilter sourceFilter;
|
||||
private CollapseBuilder collapseBuilder;
|
||||
private List<IndexBoost> indicesBoost;
|
||||
private float minScore;
|
||||
private boolean trackScores;
|
||||
@ -86,6 +89,11 @@ public class NativeSearchQueryBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public NativeSearchQueryBuilder withCollapse(String collapseField) {
|
||||
this.collapseBuilder = new CollapseBuilder(collapseField);
|
||||
return this;
|
||||
}
|
||||
|
||||
public NativeSearchQueryBuilder addAggregation(AbstractAggregationBuilder aggregationBuilder) {
|
||||
this.aggregationBuilders.add(aggregationBuilder);
|
||||
return this;
|
||||
@ -207,6 +215,10 @@ public class NativeSearchQueryBuilder {
|
||||
nativeSearchQuery.setScriptFields(scriptFields);
|
||||
}
|
||||
|
||||
if (collapseBuilder != null) {
|
||||
nativeSearchQuery.setCollapseBuilder(collapseBuilder);
|
||||
}
|
||||
|
||||
if (!isEmpty(facetRequests)) {
|
||||
nativeSearchQuery.setFacets(facetRequests);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import java.util.List;
|
||||
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
|
||||
import org.elasticsearch.search.collapse.CollapseBuilder;
|
||||
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
|
||||
import org.elasticsearch.search.sort.SortBuilder;
|
||||
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
|
||||
@ -30,6 +31,7 @@ import org.springframework.data.elasticsearch.core.facet.FacetRequest;
|
||||
* @author Mohsin Husen
|
||||
* @author Artur Konczak
|
||||
* @author Jean-Baptiste Nizet
|
||||
* @author Martin Choraine
|
||||
*/
|
||||
public interface SearchQuery extends Query {
|
||||
|
||||
@ -50,6 +52,8 @@ public interface SearchQuery extends Query {
|
||||
|
||||
List<IndexBoost> getIndicesBoost();
|
||||
|
||||
List<ScriptField> getScriptFields();
|
||||
List<ScriptField> getScriptFields();
|
||||
|
||||
CollapseBuilder getCollapseBuilder();
|
||||
|
||||
}
|
||||
|
@ -105,6 +105,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
* @author Ivan Greene
|
||||
* @author Dmitriy Yakovlev
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Martin Choraine
|
||||
* @author Farid Azaza
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ -2825,6 +2826,36 @@ public class ElasticsearchTemplateTests {
|
||||
assertThat(sampleEntities.get(2).getMessage()).isEqualTo(sampleEntity1.getMessage());
|
||||
}
|
||||
|
||||
@Test // DATAES-593
|
||||
public void shouldReturnDocumentWithCollapsedField() {
|
||||
|
||||
// given
|
||||
SampleEntity sampleEntity = SampleEntity.builder().id(randomNumeric(5)).message("message 1").rate(1)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
SampleEntity sampleEntity2 = SampleEntity.builder().id(randomNumeric(5)).message("message 2").rate(2)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
SampleEntity sampleEntit3 = SampleEntity.builder().id(randomNumeric(5)).message("message 1").rate(1)
|
||||
.version(System.currentTimeMillis()).build();
|
||||
|
||||
List<IndexQuery> indexQueries = getIndexQueries(Arrays.asList(sampleEntity, sampleEntity2, sampleEntit3));
|
||||
|
||||
elasticsearchTemplate.bulkIndex(indexQueries);
|
||||
elasticsearchTemplate.refresh(SampleEntity.class);
|
||||
|
||||
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
|
||||
.withIndices(INDEX_NAME_SAMPLE_ENTITY).withTypes(TYPE_NAME).withCollapse("rate").build();
|
||||
|
||||
// when
|
||||
Page<SampleEntity> page = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class);
|
||||
|
||||
// then
|
||||
assertThat(page).isNotNull();
|
||||
assertThat(page.getTotalElements()).isEqualTo(3);
|
||||
assertThat(page.getContent()).hasSize(2);
|
||||
assertThat(page.getContent().get(0).getMessage()).isEqualTo("message 1");
|
||||
assertThat(page.getContent().get(1).getMessage()).isEqualTo("message 2");
|
||||
}
|
||||
|
||||
private IndexQuery getIndexQuery(SampleEntity sampleEntity) {
|
||||
return new IndexQueryBuilder().withId(sampleEntity.getId()).withObject(sampleEntity)
|
||||
.withVersion(sampleEntity.getVersion()).build();
|
||||
|
@ -24,6 +24,8 @@ import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
@ -76,6 +78,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Mark Paluch
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Farid Azaza
|
||||
* @author Martin Choraine
|
||||
* @currentRead Golden Fool - Robin Hobb
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ -666,6 +669,30 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-593
|
||||
public void shouldReturnDocumentWithCollapsedField() {
|
||||
|
||||
SampleEntity entity1 = randomEntity("test message");
|
||||
entity1.setRate(1);
|
||||
SampleEntity entity2 = randomEntity("test another message");
|
||||
entity2.setRate(2);
|
||||
SampleEntity entity3 = randomEntity("test message again");
|
||||
entity3.setRate(1);
|
||||
index(entity1, entity2, entity3);
|
||||
|
||||
SearchQuery query = new NativeSearchQueryBuilder()
|
||||
.withIndices(DEFAULT_INDEX)
|
||||
.withQuery(matchAllQuery())
|
||||
.withCollapse("rate")
|
||||
.withPageable(PageRequest.of(0, 25))
|
||||
.build();
|
||||
|
||||
template.find(query, SampleEntity.class)
|
||||
.as(StepVerifier::create)
|
||||
.expectNextCount(2)
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Data
|
||||
@Document(indexName = "marvel", type = "characters")
|
||||
static class Person {
|
||||
@ -733,6 +760,7 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
|
||||
@Id private String id;
|
||||
@Field(type = Text, store = true, fielddata = true) private String message;
|
||||
private int rate;
|
||||
@Version private Long version;
|
||||
@Score private float score;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user