From c4b4a8c45d463b572b4156fe80461e925c60b3af Mon Sep 17 00:00:00 2001 From: Mohsin Husen Date: Thu, 3 Mar 2016 14:53:18 +0000 Subject: [PATCH] DATAES-188 - Source filtering feature Implementation --- .../core/ElasticsearchTemplate.java | 5 +++ .../core/query/AbstractQuery.java | 11 +++++ .../core/query/FetchSourceFilter.java | 42 +++++++++++++++++ .../core/query/FetchSourceFilterBuilder.java | 45 +++++++++++++++++++ .../core/query/NativeSearchQueryBuilder.java | 15 ++++--- .../data/elasticsearch/core/query/Query.java | 17 ++++++- .../core/query/SourceFilter.java | 28 ++++++++++++ .../core/ElasticsearchTemplateTests.java | 31 ++++++++++++- 8 files changed, 186 insertions(+), 8 deletions(-) create mode 100644 src/main/java/org/springframework/data/elasticsearch/core/query/FetchSourceFilter.java create mode 100644 src/main/java/org/springframework/data/elasticsearch/core/query/FetchSourceFilterBuilder.java create mode 100644 src/main/java/org/springframework/data/elasticsearch/core/query/SourceFilter.java diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java index 88d9aef0b..71006c4b9 100755 --- a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java @@ -954,6 +954,11 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati SearchRequestBuilder searchRequestBuilder = client.prepareSearch(toArray(query.getIndices())) .setSearchType(query.getSearchType()).setTypes(toArray(query.getTypes())); + if (query.getSourceFilter() != null) { + SourceFilter sourceFilter = query.getSourceFilter(); + searchRequestBuilder.setFetchSource(sourceFilter.getIncludes(), sourceFilter.getExcludes()); + } + if (query.getPageable() != null) { startRecord = query.getPageable().getPageNumber() * query.getPageable().getPageSize(); searchRequestBuilder.setSize(query.getPageable().getPageSize()); diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/AbstractQuery.java b/src/main/java/org/springframework/data/elasticsearch/core/query/AbstractQuery.java index 16781756b..2b7f44b56 100755 --- a/src/main/java/org/springframework/data/elasticsearch/core/query/AbstractQuery.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/AbstractQuery.java @@ -39,6 +39,7 @@ abstract class AbstractQuery implements Query { protected List indices = new ArrayList(); protected List types = new ArrayList(); protected List fields = new ArrayList(); + protected SourceFilter sourceFilter; protected float minScore; protected Collection ids; protected String route; @@ -91,6 +92,16 @@ abstract class AbstractQuery implements Query { return types; } + @Override + public void addSourceFilter(SourceFilter sourceFilter) { + this.sourceFilter = sourceFilter; + } + + @Override + public SourceFilter getSourceFilter() { + return sourceFilter; + } + @SuppressWarnings("unchecked") public final T addSort(Sort sort) { if (sort == null) { diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/FetchSourceFilter.java b/src/main/java/org/springframework/data/elasticsearch/core/query/FetchSourceFilter.java new file mode 100644 index 000000000..75e94f673 --- /dev/null +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/FetchSourceFilter.java @@ -0,0 +1,42 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core.query; + +/** + * SourceFilter implementation for providing includes and excludes. + * + * @Author Jon Tsiros + */ +public class FetchSourceFilter implements SourceFilter { + + private final String[] includes; + private final String[] excludes; + + public FetchSourceFilter(final String[] includes, final String[] excludes) { + this.includes = includes; + this.excludes = excludes; + } + + @Override + public String[] getIncludes() { + return includes; + } + + @Override + public String[] getExcludes() { + return excludes; + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/FetchSourceFilterBuilder.java b/src/main/java/org/springframework/data/elasticsearch/core/query/FetchSourceFilterBuilder.java new file mode 100644 index 000000000..fe288985f --- /dev/null +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/FetchSourceFilterBuilder.java @@ -0,0 +1,45 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core.query; + +/** + * SourceFilter builder for providing includes and excludes. + * + * @Author Jon Tsiros + */ +public class FetchSourceFilterBuilder { + + private String[] includes; + private String[] excludes; + + public FetchSourceFilterBuilder withIncludes(String... includes) { + this.includes = includes; + return this; + } + + public FetchSourceFilterBuilder withExcludes(String... excludes) { + this.excludes = excludes; + return this; + } + + public SourceFilter build() { + if (includes == null) includes = new String[0]; + if (excludes == null) excludes = new String[0]; + + SourceFilter sourceFilter = new FetchSourceFilter(includes, excludes); + return sourceFilter; + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/NativeSearchQueryBuilder.java b/src/main/java/org/springframework/data/elasticsearch/core/query/NativeSearchQueryBuilder.java index d2c486d9f..ff0298989 100755 --- a/src/main/java/org/springframework/data/elasticsearch/core/query/NativeSearchQueryBuilder.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/NativeSearchQueryBuilder.java @@ -41,13 +41,13 @@ public class NativeSearchQueryBuilder { private QueryBuilder filterBuilder; private List scriptFields = new ArrayList(); private List sortBuilders = new ArrayList(); - /*private List facetRequests = new ArrayList();*/ private List aggregationBuilders = new ArrayList(); private HighlightBuilder.Field[] highlightFields; private Pageable pageable; private String[] indices; private String[] types; private String[] fields; + private SourceFilter sourceFilter; private List indicesBoost; private float minScore; private Collection ids; @@ -114,6 +114,11 @@ public class NativeSearchQueryBuilder { return this; } + public NativeSearchQueryBuilder withSourceFilter(SourceFilter sourceFilter) { + this.sourceFilter = sourceFilter; + return this; + } + public NativeSearchQueryBuilder withMinScore(float minScore) { this.minScore = minScore; return this; @@ -151,6 +156,10 @@ public class NativeSearchQueryBuilder { if (fields != null) { nativeSearchQuery.addFields(fields); } + + if (sourceFilter != null) { + nativeSearchQuery.addSourceFilter(sourceFilter); + } if(indicesBoost != null) { nativeSearchQuery.setIndicesBoost(indicesBoost); @@ -160,10 +169,6 @@ public class NativeSearchQueryBuilder { nativeSearchQuery.setScriptFields(scriptFields); } -/* if (CollectionUtils.isNotEmpty(facetRequests)) { - nativeSearchQuery.setFacets(facetRequests); - }*/ - if (CollectionUtils.isNotEmpty(aggregationBuilders)) { nativeSearchQuery.setAggregations(aggregationBuilders); } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/Query.java b/src/main/java/org/springframework/data/elasticsearch/core/query/Query.java index 8ee137bee..8bde92f3a 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/query/Query.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/Query.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 the original author or authors. + * Copyright 2013-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -111,6 +111,21 @@ public interface Query { */ List getFields(); + /** + * Add source filter to be added as part of search request + * + * @param sourceFilter + */ + void addSourceFilter(SourceFilter sourceFilter); + + /** + * Get SourceFilter to be returned to get include and exclude source + * fields as part of search request. + * + * @return SourceFilter + */ + SourceFilter getSourceFilter(); + /** * Get minimum score * diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/SourceFilter.java b/src/main/java/org/springframework/data/elasticsearch/core/query/SourceFilter.java new file mode 100644 index 000000000..7b232db59 --- /dev/null +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/SourceFilter.java @@ -0,0 +1,28 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core.query; + +/** + * SourceFilter for providing includes and excludes. + * + * @Author Jon Tsiros + */ +public interface SourceFilter { + + String[] getIncludes(); + + String[] getExcludes(); +} diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java index b5fec45e9..94a132209 100755 --- a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java @@ -489,8 +489,8 @@ public class ElasticsearchTemplateTests { SearchQuery searchQuery = new NativeSearchQueryBuilder() .withQuery(matchAllQuery()) .withScriptField(new ScriptField("scriptedRate", - new Script("doc['rate'].value * factor", ScriptService.ScriptType.INLINE, null , params))) - .build(); + new Script("doc['rate'].value * factor", ScriptService.ScriptType.INLINE, null, params))) + .build(); Page sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); // then assertThat(sampleEntities.getTotalElements(), equalTo(1L)); @@ -646,6 +646,33 @@ public class ElasticsearchTemplateTests { assertThat(page.getContent().get(0), is(message)); } + @Test + public void shouldReturnFieldsBasedOnSourceFilter() { + // given + String documentId = randomNumeric(5); + String message = "some test message"; + SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message(message) + .version(System.currentTimeMillis()).build(); + + IndexQuery indexQuery = getIndexQuery(sampleEntity); + + elasticsearchTemplate.index(indexQuery); + elasticsearchTemplate.refresh(SampleEntity.class); + + FetchSourceFilterBuilder sourceFilter = new FetchSourceFilterBuilder(); + sourceFilter.withIncludes("message"); + + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withIndices(INDEX_NAME) + .withTypes(TYPE_NAME).withSourceFilter(sourceFilter.build()).build(); + // when + Page page = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); + // then + assertThat(page, is(notNullValue())); + assertThat(page.getTotalElements(), is(equalTo(1L))); + assertThat(page.getContent().get(0).getMessage(), is(message)); + } + + @Test public void shouldReturnSimilarResultsGivenMoreLikeThisQuery() { // given