mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-06-29 07:12:26 +00:00
Implement SourceFilters annotation.
Original Pull Request #2254 Closes #1280 Closes #2062 Closes #2146 Closes #2147 Closes #2151
This commit is contained in:
parent
954d8b0f97
commit
cf135f4cdd
@ -15,8 +15,14 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.annotations;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.data.annotation.QueryAnnotation;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Query
|
||||
@ -34,10 +40,18 @@ import java.lang.annotation.*;
|
||||
public @interface Query {
|
||||
|
||||
/**
|
||||
* @return Elasticsearch query to be used when executing query. May contain placeholders eg. ?0
|
||||
* @return Elasticsearch query to be used when executing query. May contain placeholders eg. ?0. Alias for query.
|
||||
*/
|
||||
@AliasFor("query")
|
||||
String value() default "";
|
||||
|
||||
/**
|
||||
* @return Elasticsearch query to be used when executing query. May contain placeholders eg. ?0. Alias for value
|
||||
* @since 5.0
|
||||
*/
|
||||
@AliasFor("value")
|
||||
String query() default "";
|
||||
|
||||
/**
|
||||
* Named Query Named looked up by repository.
|
||||
*
|
||||
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2022 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
|
||||
*
|
||||
* https://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.annotations;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* This annotation can be placed on repository methods to define the properties that should be requested from
|
||||
* Elasticsearch when the method is run.
|
||||
*
|
||||
* @author Alexander Torres
|
||||
* @author Peter-Josef Meisch
|
||||
* @since 5.0
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||
@Documented
|
||||
public @interface SourceFilters {
|
||||
|
||||
/**
|
||||
* Properties to be requested from Elasticsearch to be included in the response. These can be passed in as literals
|
||||
* like
|
||||
*
|
||||
* <pre>
|
||||
* {@code @SourceFilters(includes = {"property1", "property2"})}
|
||||
* </pre>
|
||||
*
|
||||
* or as a parameterized value
|
||||
*
|
||||
* <pre>
|
||||
* {@code @SourceFilters(includes = "?0")}
|
||||
* </pre>
|
||||
*
|
||||
* when the list of properties is passed as a function parameter.
|
||||
*/
|
||||
String[] includes() default "";
|
||||
|
||||
/**
|
||||
* Properties to be requested from Elasticsearch to be excluded in the response. These can be passed in as literals
|
||||
* like
|
||||
*
|
||||
* <pre>
|
||||
* {@code @SourceFilters(excludes = {"property1", "property2"})}
|
||||
* </pre>
|
||||
*
|
||||
* or as a parameterized value
|
||||
*
|
||||
* <pre>
|
||||
* {@code @SourceFilters(excludes = "?0")}
|
||||
* </pre>
|
||||
*
|
||||
* when the list of properties is passed as a function parameter.
|
||||
*/
|
||||
String[] excludes() default "";
|
||||
}
|
@ -16,6 +16,9 @@
|
||||
package org.springframework.data.elasticsearch.repository.query;
|
||||
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
|
||||
@ -31,12 +34,14 @@ public abstract class AbstractElasticsearchRepositoryQuery implements Repository
|
||||
|
||||
protected static final int DEFAULT_STREAM_BATCH_SIZE = 500;
|
||||
protected ElasticsearchQueryMethod queryMethod;
|
||||
protected ElasticsearchOperations elasticsearchOperations;
|
||||
protected final ElasticsearchOperations elasticsearchOperations;
|
||||
protected final ElasticsearchConverter elasticsearchConverter;
|
||||
|
||||
public AbstractElasticsearchRepositoryQuery(ElasticsearchQueryMethod queryMethod,
|
||||
ElasticsearchOperations elasticsearchOperations) {
|
||||
this.queryMethod = queryMethod;
|
||||
this.elasticsearchOperations = elasticsearchOperations;
|
||||
this.elasticsearchConverter = elasticsearchOperations.getElasticsearchConverter();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -49,4 +54,19 @@ public abstract class AbstractElasticsearchRepositoryQuery implements Repository
|
||||
* @since 4.2
|
||||
*/
|
||||
public abstract boolean isCountQuery();
|
||||
|
||||
protected void prepareQuery(Query query, Class<?> clazz, ParameterAccessor parameterAccessor) {
|
||||
|
||||
elasticsearchConverter.updateQuery(query, clazz);
|
||||
|
||||
if (queryMethod.hasAnnotatedHighlight()) {
|
||||
query.setHighlightQuery(queryMethod.getAnnotatedHighlightQuery());
|
||||
}
|
||||
|
||||
var sourceFilter = queryMethod.getSourceFilter(parameterAccessor,
|
||||
elasticsearchOperations.getElasticsearchConverter());
|
||||
if (sourceFilter != null) {
|
||||
query.addSourceFilter(sourceFilter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersiste
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.query.ByQueryResponse;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.elasticsearch.core.query.SourceFilter;
|
||||
import org.springframework.data.elasticsearch.repository.query.ReactiveElasticsearchQueryExecution.ResultProcessingConverter;
|
||||
import org.springframework.data.elasticsearch.repository.query.ReactiveElasticsearchQueryExecution.ResultProcessingExecution;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
@ -88,6 +89,12 @@ abstract class AbstractReactiveElasticsearchRepositoryQuery implements Repositor
|
||||
query.setHighlightQuery(queryMethod.getAnnotatedHighlightQuery());
|
||||
}
|
||||
|
||||
var sourceFilter = queryMethod.getSourceFilter(parameterAccessor,
|
||||
elasticsearchOperations.getElasticsearchConverter());
|
||||
if (sourceFilter != null) {
|
||||
query.addSourceFilter(sourceFilter);
|
||||
}
|
||||
|
||||
Class<?> targetType = processor.getReturnedType().getTypeToRead();
|
||||
String indexName = queryMethod.getEntityInformation().getIndexName();
|
||||
IndexCoordinates index = IndexCoordinates.of(indexName);
|
||||
|
@ -23,7 +23,6 @@ import org.springframework.data.elasticsearch.core.SearchHitSupport;
|
||||
import org.springframework.data.elasticsearch.core.SearchHits;
|
||||
import org.springframework.data.elasticsearch.core.SearchHitsImpl;
|
||||
import org.springframework.data.elasticsearch.core.TotalHitsRelation;
|
||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
||||
@ -49,13 +48,11 @@ import org.springframework.util.ClassUtils;
|
||||
public class ElasticsearchPartQuery extends AbstractElasticsearchRepositoryQuery {
|
||||
|
||||
private final PartTree tree;
|
||||
private final ElasticsearchConverter elasticsearchConverter;
|
||||
private final MappingContext<?, ElasticsearchPersistentProperty> mappingContext;
|
||||
|
||||
public ElasticsearchPartQuery(ElasticsearchQueryMethod method, ElasticsearchOperations elasticsearchOperations) {
|
||||
super(method, elasticsearchOperations);
|
||||
this.tree = new PartTree(queryMethod.getName(), queryMethod.getResultProcessor().getReturnedType().getDomainType());
|
||||
this.elasticsearchConverter = elasticsearchOperations.getElasticsearchConverter();
|
||||
this.mappingContext = elasticsearchConverter.getMappingContext();
|
||||
}
|
||||
|
||||
@ -66,18 +63,16 @@ public class ElasticsearchPartQuery extends AbstractElasticsearchRepositoryQuery
|
||||
|
||||
@Override
|
||||
public Object execute(Object[] parameters) {
|
||||
Class<?> clazz = queryMethod.getResultProcessor().getReturnedType().getDomainType();
|
||||
ParametersParameterAccessor accessor = new ParametersParameterAccessor(queryMethod.getParameters(), parameters);
|
||||
|
||||
CriteriaQuery query = createQuery(accessor);
|
||||
Class<?> clazz = queryMethod.getResultProcessor().getReturnedType().getDomainType();
|
||||
ParametersParameterAccessor parameterAccessor = new ParametersParameterAccessor(queryMethod.getParameters(),
|
||||
parameters);
|
||||
|
||||
CriteriaQuery query = createQuery(parameterAccessor);
|
||||
|
||||
Assert.notNull(query, "unsupported query");
|
||||
|
||||
elasticsearchConverter.updateQuery(query, clazz);
|
||||
|
||||
if (queryMethod.hasAnnotatedHighlight()) {
|
||||
query.setHighlightQuery(queryMethod.getAnnotatedHighlightQuery());
|
||||
}
|
||||
prepareQuery(query, clazz, parameterAccessor);
|
||||
|
||||
IndexCoordinates index = elasticsearchOperations.getIndexCoordinatesFor(clazz);
|
||||
|
||||
@ -89,11 +84,11 @@ public class ElasticsearchPartQuery extends AbstractElasticsearchRepositoryQuery
|
||||
}
|
||||
|
||||
if (tree.isDelete()) {
|
||||
result = countOrGetDocumentsForDelete(query, accessor);
|
||||
result = countOrGetDocumentsForDelete(query, parameterAccessor);
|
||||
elasticsearchOperations.delete(query, clazz, index);
|
||||
elasticsearchOperations.indexOps(index).refresh();
|
||||
} else if (queryMethod.isPageQuery()) {
|
||||
query.setPageable(accessor.getPageable());
|
||||
query.setPageable(parameterAccessor.getPageable());
|
||||
SearchHits<?> searchHits = elasticsearchOperations.search(query, clazz, index);
|
||||
if (queryMethod.isSearchPageMethod()) {
|
||||
result = SearchHitSupport.searchPageFor(searchHits, query.getPageable());
|
||||
@ -101,15 +96,15 @@ public class ElasticsearchPartQuery extends AbstractElasticsearchRepositoryQuery
|
||||
result = SearchHitSupport.unwrapSearchHits(SearchHitSupport.searchPageFor(searchHits, query.getPageable()));
|
||||
}
|
||||
} else if (queryMethod.isStreamQuery()) {
|
||||
if (accessor.getPageable().isUnpaged()) {
|
||||
if (parameterAccessor.getPageable().isUnpaged()) {
|
||||
query.setPageable(PageRequest.of(0, DEFAULT_STREAM_BATCH_SIZE));
|
||||
} else {
|
||||
query.setPageable(accessor.getPageable());
|
||||
query.setPageable(parameterAccessor.getPageable());
|
||||
}
|
||||
result = StreamUtils.createStreamFromIterator(elasticsearchOperations.searchForStream(query, clazz, index));
|
||||
} else if (queryMethod.isCollectionQuery()) {
|
||||
|
||||
if (accessor.getPageable().isUnpaged()) {
|
||||
if (parameterAccessor.getPageable().isUnpaged()) {
|
||||
int itemCount = (int) elasticsearchOperations.count(query, clazz, index);
|
||||
|
||||
if (itemCount == 0) {
|
||||
@ -119,7 +114,7 @@ public class ElasticsearchPartQuery extends AbstractElasticsearchRepositoryQuery
|
||||
query.setPageable(PageRequest.of(0, Math.max(1, itemCount)));
|
||||
}
|
||||
} else {
|
||||
query.setPageable(accessor.getPageable());
|
||||
query.setPageable(parameterAccessor.getPageable());
|
||||
}
|
||||
|
||||
if (result == null) {
|
||||
|
@ -17,22 +17,31 @@ package org.springframework.data.elasticsearch.repository.query;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.elasticsearch.annotations.Highlight;
|
||||
import org.springframework.data.elasticsearch.annotations.Query;
|
||||
import org.springframework.data.elasticsearch.annotations.SourceFilters;
|
||||
import org.springframework.data.elasticsearch.core.SearchHit;
|
||||
import org.springframework.data.elasticsearch.core.SearchHits;
|
||||
import org.springframework.data.elasticsearch.core.SearchPage;
|
||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
|
||||
import org.springframework.data.elasticsearch.core.query.FetchSourceFilterBuilder;
|
||||
import org.springframework.data.elasticsearch.core.query.HighlightQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.SourceFilter;
|
||||
import org.springframework.data.elasticsearch.repository.support.StringQueryUtil;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.data.util.Lazy;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
@ -49,16 +58,19 @@ import org.springframework.util.ClassUtils;
|
||||
* @author Mark Paluch
|
||||
* @author Christoph Strobl
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Alexander Torres
|
||||
*/
|
||||
public class ElasticsearchQueryMethod extends QueryMethod {
|
||||
|
||||
private final MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext;
|
||||
private @Nullable ElasticsearchEntityMetadata<?> metadata;
|
||||
@Nullable private ElasticsearchEntityMetadata<?> metadata;
|
||||
protected final Method method; // private in base class, but needed here and in derived classes as well
|
||||
@Nullable private final Query queryAnnotation;
|
||||
@Nullable private final Highlight highlightAnnotation;
|
||||
private final Lazy<HighlightQuery> highlightQueryLazy = Lazy.of(this::createAnnotatedHighlightQuery);
|
||||
|
||||
@Nullable private final SourceFilters sourceFilters;
|
||||
|
||||
public ElasticsearchQueryMethod(Method method, RepositoryMetadata repositoryMetadata, ProjectionFactory factory,
|
||||
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext) {
|
||||
|
||||
@ -70,6 +82,7 @@ public class ElasticsearchQueryMethod extends QueryMethod {
|
||||
this.mappingContext = mappingContext;
|
||||
this.queryAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, Query.class);
|
||||
this.highlightAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, Highlight.class);
|
||||
this.sourceFilters = AnnotatedElementUtils.findMergedAnnotation(method, SourceFilters.class);
|
||||
|
||||
verifyCountQueryTypes();
|
||||
}
|
||||
@ -92,8 +105,9 @@ public class ElasticsearchQueryMethod extends QueryMethod {
|
||||
/**
|
||||
* @return the query String. Must not be {@literal null} when {@link #hasAnnotatedQuery()} returns true
|
||||
*/
|
||||
@Nullable
|
||||
public String getAnnotatedQuery() {
|
||||
return queryAnnotation.value();
|
||||
return queryAnnotation != null ? queryAnnotation.value() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -246,4 +260,86 @@ public class ElasticsearchQueryMethod extends QueryMethod {
|
||||
return queryAnnotation != null && queryAnnotation.count();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} if the method is annotated with {@link SourceFilters}.
|
||||
* @since 5.0
|
||||
*/
|
||||
public boolean hasSourceFilters() {
|
||||
return sourceFilters != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link SourceFilters} annotation for this method.
|
||||
* @since 5.0
|
||||
*/
|
||||
@Nullable
|
||||
public SourceFilters getSourceFilters() {
|
||||
return sourceFilters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the sourceFilters property to create a {@link SourceFilter} to be added to a
|
||||
* {@link org.springframework.data.elasticsearch.core.query.Query}
|
||||
*
|
||||
* @param parameterAccessor the accessor with the query method parameter details
|
||||
* @param converter {@link ElasticsearchConverter} needed to convert entity property names to the Elasticsearch field
|
||||
* names and for parameter conversion when the includes or excludes are defined as parameters
|
||||
* @return source filter with includes and excludes for a query, {@literal null} when no {@link SourceFilters}
|
||||
* annotation was set on the method.
|
||||
* @since 5.0
|
||||
*/
|
||||
@Nullable
|
||||
SourceFilter getSourceFilter(ParameterAccessor parameterAccessor, ElasticsearchConverter converter) {
|
||||
|
||||
if (sourceFilters == null || (sourceFilters.includes().length == 0 && sourceFilters.excludes().length == 0)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ElasticsearchPersistentEntity<?> persistentEntity = converter.getMappingContext()
|
||||
.getPersistentEntity(getEntityInformation().getJavaType());
|
||||
|
||||
StringQueryUtil stringQueryUtil = new StringQueryUtil(converter.getConversionService());
|
||||
FetchSourceFilterBuilder fetchSourceFilterBuilder = new FetchSourceFilterBuilder();
|
||||
|
||||
if (sourceFilters.includes().length > 0) {
|
||||
fetchSourceFilterBuilder
|
||||
.withIncludes(mapParameters(sourceFilters.includes(), parameterAccessor, stringQueryUtil, persistentEntity));
|
||||
}
|
||||
|
||||
if (sourceFilters.excludes().length > 0) {
|
||||
fetchSourceFilterBuilder
|
||||
.withExcludes(mapParameters(sourceFilters.excludes(), parameterAccessor, stringQueryUtil, persistentEntity));
|
||||
}
|
||||
|
||||
return fetchSourceFilterBuilder.build();
|
||||
}
|
||||
|
||||
private String[] mapParameters(String[] source, ParameterAccessor parameterAccessor, StringQueryUtil stringQueryUtil,
|
||||
@Nullable ElasticsearchPersistentEntity<?> persistentEntity) {
|
||||
|
||||
List<String> unmappedFieldNames = new ArrayList<>();
|
||||
|
||||
for (String s : source) {
|
||||
|
||||
if (!s.isBlank()) {
|
||||
String fieldName = stringQueryUtil.replacePlaceholders(s, parameterAccessor);
|
||||
// this could be "[\"foo\",\"bar\"]", must be split
|
||||
if (fieldName.startsWith("[") && fieldName.endsWith("]")) {
|
||||
unmappedFieldNames.addAll( //
|
||||
Arrays.asList(fieldName.substring(1, fieldName.length() - 2) //
|
||||
.replaceAll("\\\"", "") //
|
||||
.split(","))); //
|
||||
} else {
|
||||
unmappedFieldNames.add(fieldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return unmappedFieldNames.stream().map(fieldName -> {
|
||||
ElasticsearchPersistentProperty property = persistentEntity != null
|
||||
? persistentEntity.getPersistentProperty(fieldName)
|
||||
: null;
|
||||
return property != null ? property.getFieldName() : fieldName;
|
||||
}).toArray(String[]::new);
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.SearchHitSupport;
|
||||
import org.springframework.data.elasticsearch.core.SearchHits;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.elasticsearch.core.query.StringQuery;
|
||||
import org.springframework.data.elasticsearch.repository.support.StringQueryUtil;
|
||||
import org.springframework.data.repository.query.ParametersParameterAccessor;
|
||||
@ -38,13 +39,13 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class ElasticsearchStringQuery extends AbstractElasticsearchRepositoryQuery {
|
||||
|
||||
private String query;
|
||||
private final String queryString;
|
||||
|
||||
public ElasticsearchStringQuery(ElasticsearchQueryMethod queryMethod, ElasticsearchOperations elasticsearchOperations,
|
||||
String query) {
|
||||
String queryString) {
|
||||
super(queryMethod, elasticsearchOperations);
|
||||
Assert.notNull(query, "Query cannot be empty");
|
||||
this.query = query;
|
||||
Assert.notNull(queryString, "Query cannot be empty");
|
||||
this.queryString = queryString;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -56,40 +57,42 @@ public class ElasticsearchStringQuery extends AbstractElasticsearchRepositoryQue
|
||||
public Object execute(Object[] parameters) {
|
||||
|
||||
Class<?> clazz = queryMethod.getResultProcessor().getReturnedType().getDomainType();
|
||||
ParametersParameterAccessor accessor = new ParametersParameterAccessor(queryMethod.getParameters(), parameters);
|
||||
ParametersParameterAccessor parameterAccessor = new ParametersParameterAccessor(queryMethod.getParameters(),
|
||||
parameters);
|
||||
|
||||
StringQuery stringQuery = createQuery(accessor);
|
||||
|
||||
Assert.notNull(stringQuery, "unsupported query");
|
||||
Query query = createQuery(parameterAccessor);
|
||||
Assert.notNull(query, "unsupported query");
|
||||
|
||||
if (queryMethod.hasAnnotatedHighlight()) {
|
||||
stringQuery.setHighlightQuery(queryMethod.getAnnotatedHighlightQuery());
|
||||
query.setHighlightQuery(queryMethod.getAnnotatedHighlightQuery());
|
||||
}
|
||||
|
||||
prepareQuery(query, clazz, parameterAccessor);
|
||||
|
||||
IndexCoordinates index = elasticsearchOperations.getIndexCoordinatesFor(clazz);
|
||||
|
||||
Object result = null;
|
||||
Object result;
|
||||
|
||||
if (isCountQuery()) {
|
||||
result = elasticsearchOperations.count(stringQuery, clazz, index);
|
||||
result = elasticsearchOperations.count(query, clazz, index);
|
||||
} else if (queryMethod.isPageQuery()) {
|
||||
stringQuery.setPageable(accessor.getPageable());
|
||||
SearchHits<?> searchHits = elasticsearchOperations.search(stringQuery, clazz, index);
|
||||
query.setPageable(parameterAccessor.getPageable());
|
||||
SearchHits<?> searchHits = elasticsearchOperations.search(query, clazz, index);
|
||||
if (queryMethod.isSearchPageMethod()) {
|
||||
result = SearchHitSupport.searchPageFor(searchHits, stringQuery.getPageable());
|
||||
result = SearchHitSupport.searchPageFor(searchHits, query.getPageable());
|
||||
} else {
|
||||
result = SearchHitSupport
|
||||
.unwrapSearchHits(SearchHitSupport.searchPageFor(searchHits, stringQuery.getPageable()));
|
||||
result = SearchHitSupport.unwrapSearchHits(SearchHitSupport.searchPageFor(searchHits, query.getPageable()));
|
||||
}
|
||||
} else if (queryMethod.isStreamQuery()) {
|
||||
stringQuery.setPageable(
|
||||
accessor.getPageable().isPaged() ? accessor.getPageable() : PageRequest.of(0, DEFAULT_STREAM_BATCH_SIZE));
|
||||
result = StreamUtils.createStreamFromIterator(elasticsearchOperations.searchForStream(stringQuery, clazz, index));
|
||||
query.setPageable(parameterAccessor.getPageable().isPaged() ? parameterAccessor.getPageable()
|
||||
: PageRequest.of(0, DEFAULT_STREAM_BATCH_SIZE));
|
||||
result = StreamUtils.createStreamFromIterator(elasticsearchOperations.searchForStream(query, clazz, index));
|
||||
} else if (queryMethod.isCollectionQuery()) {
|
||||
stringQuery.setPageable(accessor.getPageable().isPaged() ? accessor.getPageable() : Pageable.unpaged());
|
||||
result = elasticsearchOperations.search(stringQuery, clazz, index);
|
||||
query.setPageable(
|
||||
parameterAccessor.getPageable().isPaged() ? parameterAccessor.getPageable() : Pageable.unpaged());
|
||||
result = elasticsearchOperations.search(query, clazz, index);
|
||||
} else {
|
||||
result = elasticsearchOperations.searchOne(stringQuery, clazz, index);
|
||||
result = elasticsearchOperations.searchOne(query, clazz, index);
|
||||
}
|
||||
|
||||
return (queryMethod.isNotSearchHitMethod() && queryMethod.isNotSearchPageMethod())
|
||||
@ -99,7 +102,7 @@ public class ElasticsearchStringQuery extends AbstractElasticsearchRepositoryQue
|
||||
|
||||
protected StringQuery createQuery(ParametersParameterAccessor parameterAccessor) {
|
||||
String queryString = new StringQueryUtil(elasticsearchOperations.getElasticsearchConverter().getConversionService())
|
||||
.replacePlaceholders(this.query, parameterAccessor);
|
||||
.replacePlaceholders(this.queryString, parameterAccessor);
|
||||
return new StringQuery(queryString);
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,7 @@ import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.annotations.Highlight;
|
||||
import org.springframework.data.elasticsearch.annotations.HighlightField;
|
||||
import org.springframework.data.elasticsearch.annotations.Query;
|
||||
import org.springframework.data.elasticsearch.annotations.SourceFilters;
|
||||
import org.springframework.data.elasticsearch.core.AbstractElasticsearchTemplate;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.SearchHit;
|
||||
@ -80,12 +81,11 @@ import org.springframework.lang.Nullable;
|
||||
@SpringIntegrationTest
|
||||
public abstract class CustomMethodRepositoryIntegrationTests implements NewElasticsearchClientDevelopment {
|
||||
|
||||
@Autowired ElasticsearchOperations operations;
|
||||
@Autowired private IndexNameProvider indexNameProvider;
|
||||
@Autowired private SampleCustomMethodRepository repository;
|
||||
@Autowired private SampleStreamingCustomMethodRepository streamingRepository;
|
||||
|
||||
@Autowired ElasticsearchOperations operations;
|
||||
|
||||
boolean rhlcWithCluster8() {
|
||||
var clusterVersion = ((AbstractElasticsearchTemplate) operations).getClusterVersion();
|
||||
return (oldElasticsearchClient() && clusterVersion != null && clusterVersion.startsWith("8"));
|
||||
@ -1675,6 +1675,94 @@ public abstract class CustomMethodRepositoryIntegrationTests implements NewElast
|
||||
assertThat(returnedIds).containsAll(ids);
|
||||
}
|
||||
|
||||
@Test // #2146
|
||||
@DisplayName("should use sourceIncludes from annotation")
|
||||
void shouldUseSourceIncludesFromAnnotation() {
|
||||
|
||||
SampleEntity entity = new SampleEntity();
|
||||
entity.setId("42");
|
||||
entity.setMessage("message");
|
||||
entity.setCustomFieldNameMessage("customFieldNameMessage");
|
||||
entity.setType("type");
|
||||
entity.setKeyword("keyword");
|
||||
repository.save(entity);
|
||||
|
||||
var searchHits = repository.searchWithSourceFilterIncludesAnnotation();
|
||||
|
||||
assertThat(searchHits.hasSearchHits()).isTrue();
|
||||
var foundEntity = searchHits.getSearchHit(0).getContent();
|
||||
assertThat(foundEntity.getMessage()).isEqualTo("message");
|
||||
assertThat(foundEntity.getCustomFieldNameMessage()).isEqualTo("customFieldNameMessage");
|
||||
assertThat(foundEntity.getType()).isNull();
|
||||
assertThat(foundEntity.getKeyword()).isNull();
|
||||
}
|
||||
|
||||
@Test // #2146
|
||||
@DisplayName("should use sourceIncludes from parameter")
|
||||
void shouldUseSourceIncludesFromParameter() {
|
||||
|
||||
SampleEntity entity = new SampleEntity();
|
||||
entity.setId("42");
|
||||
entity.setMessage("message");
|
||||
entity.setCustomFieldNameMessage("customFieldNameMessage");
|
||||
entity.setType("type");
|
||||
entity.setKeyword("keyword");
|
||||
repository.save(entity);
|
||||
|
||||
var searchHits = repository.searchBy(List.of("message", "customFieldNameMessage"));
|
||||
|
||||
assertThat(searchHits.hasSearchHits()).isTrue();
|
||||
var foundEntity = searchHits.getSearchHit(0).getContent();
|
||||
assertThat(foundEntity.getMessage()).isEqualTo("message");
|
||||
assertThat(foundEntity.getCustomFieldNameMessage()).isEqualTo("customFieldNameMessage");
|
||||
assertThat(foundEntity.getType()).isNull();
|
||||
assertThat(foundEntity.getKeyword()).isNull();
|
||||
}
|
||||
|
||||
@Test // #2146
|
||||
@DisplayName("should use sourceExcludes from annotation")
|
||||
void shouldUseSourceExcludesFromAnnotation() {
|
||||
|
||||
SampleEntity entity = new SampleEntity();
|
||||
entity.setId("42");
|
||||
entity.setMessage("message");
|
||||
entity.setCustomFieldNameMessage("customFieldNameMessage");
|
||||
entity.setType("type");
|
||||
entity.setKeyword("keyword");
|
||||
repository.save(entity);
|
||||
|
||||
var searchHits = repository.searchWithSourceFilterExcludesAnnotation();
|
||||
|
||||
assertThat(searchHits.hasSearchHits()).isTrue();
|
||||
var foundEntity = searchHits.getSearchHit(0).getContent();
|
||||
assertThat(foundEntity.getMessage()).isEqualTo("message");
|
||||
assertThat(foundEntity.getCustomFieldNameMessage()).isEqualTo("customFieldNameMessage");
|
||||
assertThat(foundEntity.getType()).isNull();
|
||||
assertThat(foundEntity.getKeyword()).isNull();
|
||||
}
|
||||
|
||||
@Test // #2146
|
||||
@DisplayName("should use source excludes from parameter")
|
||||
void shouldUseSourceExcludesFromParameter() {
|
||||
|
||||
SampleEntity entity = new SampleEntity();
|
||||
entity.setId("42");
|
||||
entity.setMessage("message");
|
||||
entity.setCustomFieldNameMessage("customFieldNameMessage");
|
||||
entity.setType("type");
|
||||
entity.setKeyword("keyword");
|
||||
repository.save(entity);
|
||||
|
||||
var searchHits = repository.findBy(List.of("type", "keyword"));
|
||||
|
||||
assertThat(searchHits.hasSearchHits()).isTrue();
|
||||
var foundEntity = searchHits.getSearchHit(0).getContent();
|
||||
assertThat(foundEntity.getMessage()).isEqualTo("message");
|
||||
assertThat(foundEntity.getCustomFieldNameMessage()).isEqualTo("customFieldNameMessage");
|
||||
assertThat(foundEntity.getType()).isNull();
|
||||
assertThat(foundEntity.getKeyword()).isNull();
|
||||
}
|
||||
|
||||
private List<SampleEntity> createSampleEntities(String type, int numberOfEntities) {
|
||||
|
||||
List<SampleEntity> entities = new ArrayList<>();
|
||||
@ -1690,93 +1778,6 @@ public abstract class CustomMethodRepositoryIntegrationTests implements NewElast
|
||||
return entities;
|
||||
}
|
||||
|
||||
@Document(indexName = "#{@indexNameProvider.indexName()}")
|
||||
static class SampleEntity {
|
||||
@Nullable
|
||||
@Id private String id;
|
||||
@Nullable
|
||||
@Field(type = Text, store = true, fielddata = true) private String type;
|
||||
@Nullable
|
||||
@Field(type = Text, store = true, fielddata = true) private String message;
|
||||
@Nullable
|
||||
@Field(type = Keyword) private String keyword;
|
||||
@Nullable private int rate;
|
||||
@Nullable private boolean available;
|
||||
@Nullable private GeoPoint location;
|
||||
@Nullable
|
||||
@Version private Long version;
|
||||
|
||||
@Nullable
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(@Nullable String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(@Nullable String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(@Nullable String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getKeyword() {
|
||||
return keyword;
|
||||
}
|
||||
|
||||
public void setKeyword(@Nullable String keyword) {
|
||||
this.keyword = keyword;
|
||||
}
|
||||
|
||||
public int getRate() {
|
||||
return rate;
|
||||
}
|
||||
|
||||
public void setRate(int rate) {
|
||||
this.rate = rate;
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return available;
|
||||
}
|
||||
|
||||
public void setAvailable(boolean available) {
|
||||
this.available = available;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GeoPoint getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public void setLocation(@Nullable GeoPoint location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public java.lang.Long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(@Nullable java.lang.Long version) {
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
@ -1911,11 +1912,30 @@ public abstract class CustomMethodRepositoryIntegrationTests implements NewElast
|
||||
|
||||
@Query("{\"ids\" : {\"values\" : ?0 }}")
|
||||
List<SampleEntity> getByIds(Collection<String> ids);
|
||||
|
||||
@Query("""
|
||||
{
|
||||
"match_all": {}
|
||||
}
|
||||
""")
|
||||
@SourceFilters(includes = { "message", "customFieldNameMessage" })
|
||||
SearchHits<SampleEntity> searchWithSourceFilterIncludesAnnotation();
|
||||
|
||||
@SourceFilters(includes = "?0")
|
||||
SearchHits<SampleEntity> searchBy(Collection<String> sourceIncludes);
|
||||
|
||||
@Query("""
|
||||
{
|
||||
"match_all": {}
|
||||
}
|
||||
""")
|
||||
@SourceFilters(excludes = { "type", "keyword" })
|
||||
SearchHits<SampleEntity> searchWithSourceFilterExcludesAnnotation();
|
||||
|
||||
@SourceFilters(excludes = "?0")
|
||||
SearchHits<SampleEntity> findBy(Collection<String> sourceExcludes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Rasmus Faber-Espensen
|
||||
*/
|
||||
public interface SampleStreamingCustomMethodRepository extends ElasticsearchRepository<SampleEntity, String> {
|
||||
Stream<SampleEntity> findByType(String type);
|
||||
|
||||
@ -1928,4 +1948,103 @@ public abstract class CustomMethodRepositoryIntegrationTests implements NewElast
|
||||
Stream<SearchHit<SampleEntity>> streamSearchHitsByType(String type);
|
||||
|
||||
}
|
||||
|
||||
@Document(indexName = "#{@indexNameProvider.indexName()}")
|
||||
static class SampleEntity {
|
||||
@Nullable
|
||||
@Id private String id;
|
||||
@Nullable
|
||||
@Field(type = Text, store = true, fielddata = true) private String type;
|
||||
@Nullable
|
||||
@Field(type = Text, store = true, fielddata = true) private String message;
|
||||
@Nullable
|
||||
@Field(type = Keyword) private String keyword;
|
||||
@Nullable private int rate;
|
||||
@Nullable private boolean available;
|
||||
@Nullable private GeoPoint location;
|
||||
@Nullable
|
||||
@Version private Long version;
|
||||
|
||||
@Field(name = "custom_field_name", type = Text)
|
||||
@Nullable private String customFieldNameMessage;
|
||||
|
||||
@Nullable
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(@Nullable String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(@Nullable String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(@Nullable String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getCustomFieldNameMessage() {
|
||||
return customFieldNameMessage;
|
||||
}
|
||||
|
||||
public void setCustomFieldNameMessage(@Nullable String customFieldNameMessage) {
|
||||
this.customFieldNameMessage = customFieldNameMessage;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getKeyword() {
|
||||
return keyword;
|
||||
}
|
||||
|
||||
public void setKeyword(@Nullable String keyword) {
|
||||
this.keyword = keyword;
|
||||
}
|
||||
|
||||
public int getRate() {
|
||||
return rate;
|
||||
}
|
||||
|
||||
public void setRate(int rate) {
|
||||
this.rate = rate;
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return available;
|
||||
}
|
||||
|
||||
public void setAvailable(boolean available) {
|
||||
this.available = available;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GeoPoint getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public void setLocation(@Nullable GeoPoint location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public java.lang.Long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(@Nullable java.lang.Long version) {
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
@ -47,6 +48,7 @@ import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||
import org.springframework.data.elasticsearch.annotations.Highlight;
|
||||
import org.springframework.data.elasticsearch.annotations.HighlightField;
|
||||
import org.springframework.data.elasticsearch.annotations.Query;
|
||||
import org.springframework.data.elasticsearch.annotations.SourceFilters;
|
||||
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.SearchHit;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
@ -634,6 +636,98 @@ abstract class SimpleReactiveElasticsearchRepositoryIntegrationTests {
|
||||
|
||||
}
|
||||
|
||||
@Test // #2146
|
||||
@DisplayName("should use sourceIncludes from annotation")
|
||||
void shouldUseSourceIncludesFromAnnotation() {
|
||||
|
||||
var entity = new SampleEntity();
|
||||
entity.setId("42");
|
||||
entity.setMessage("message");
|
||||
entity.setCustomFieldNameMessage("customFieldNameMessage");
|
||||
entity.setType("type");
|
||||
entity.setKeyword("keyword");
|
||||
repository.save(entity).block();
|
||||
|
||||
repository.searchWithSourceFilterIncludesAnnotation() //
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(foundEntity -> { //
|
||||
assertThat(foundEntity.getMessage()).isEqualTo("message"); //
|
||||
assertThat(foundEntity.getCustomFieldNameMessage()).isEqualTo("customFieldNameMessage"); //
|
||||
assertThat(foundEntity.getType()).isNull(); //
|
||||
assertThat(foundEntity.getKeyword()).isNull(); //
|
||||
}) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // #2146
|
||||
@DisplayName("should use sourceIncludes from parameter")
|
||||
void shouldUseSourceIncludesFromParameter() {
|
||||
|
||||
var entity = new SampleEntity();
|
||||
entity.setId("42");
|
||||
entity.setMessage("message");
|
||||
entity.setCustomFieldNameMessage("customFieldNameMessage");
|
||||
entity.setType("type");
|
||||
entity.setKeyword("keyword");
|
||||
repository.save(entity).block();
|
||||
|
||||
repository.searchBy(List.of("message", "customFieldNameMessage")) //
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(foundEntity -> { //
|
||||
assertThat(foundEntity.getMessage()).isEqualTo("message"); //
|
||||
assertThat(foundEntity.getCustomFieldNameMessage()).isEqualTo("customFieldNameMessage"); //
|
||||
assertThat(foundEntity.getType()).isNull(); //
|
||||
assertThat(foundEntity.getKeyword()).isNull(); //
|
||||
}) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // #2146
|
||||
@DisplayName("should use sourceExcludes from annotation")
|
||||
void shouldUseSourceExcludesFromAnnotation() {
|
||||
|
||||
var entity = new SampleEntity();
|
||||
entity.setId("42");
|
||||
entity.setMessage("message");
|
||||
entity.setCustomFieldNameMessage("customFieldNameMessage");
|
||||
entity.setType("type");
|
||||
entity.setKeyword("keyword");
|
||||
repository.save(entity).block();
|
||||
|
||||
repository.searchWithSourceFilterExcludesAnnotation() //
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(foundEntity -> { //
|
||||
assertThat(foundEntity.getMessage()).isEqualTo("message"); //
|
||||
assertThat(foundEntity.getCustomFieldNameMessage()).isEqualTo("customFieldNameMessage"); //
|
||||
assertThat(foundEntity.getType()).isNull(); //
|
||||
assertThat(foundEntity.getKeyword()).isNull(); //
|
||||
}) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // #2146
|
||||
@DisplayName("should use source excludes from parameter")
|
||||
void shouldUseSourceExcludesFromParameter() {
|
||||
|
||||
var entity = new SampleEntity();
|
||||
entity.setId("42");
|
||||
entity.setMessage("message");
|
||||
entity.setCustomFieldNameMessage("customFieldNameMessage");
|
||||
entity.setType("type");
|
||||
entity.setKeyword("keyword");
|
||||
repository.save(entity).block();
|
||||
|
||||
repository.findBy(List.of("type", "keyword")) //
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(foundEntity -> { //
|
||||
assertThat(foundEntity.getMessage()).isEqualTo("message"); //
|
||||
assertThat(foundEntity.getCustomFieldNameMessage()).isEqualTo("customFieldNameMessage"); //
|
||||
assertThat(foundEntity.getType()).isNull(); //
|
||||
assertThat(foundEntity.getKeyword()).isNull(); //
|
||||
}) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
Mono<Void> bulkIndex(SampleEntity... entities) {
|
||||
return operations.saveAll(Arrays.asList(entities), IndexCoordinates.of(indexNameProvider.indexName())).then();
|
||||
}
|
||||
@ -683,6 +777,27 @@ abstract class SimpleReactiveElasticsearchRepositoryIntegrationTests {
|
||||
@Query("{\"bool\": {\"must\": [{ \"terms\": { \"message\": ?0 } }, { \"terms\": { \"rate\": ?1 } }] } }")
|
||||
Flux<SampleEntity> findAllViaAnnotatedQueryByMessageInAndRatesIn(List<String> messages, List<Integer> rates);
|
||||
|
||||
@Query(query = """
|
||||
{
|
||||
"match_all": {}
|
||||
}
|
||||
""")
|
||||
@SourceFilters(includes = { "message", "customFieldNameMessage" })
|
||||
Flux<SampleEntity> searchWithSourceFilterIncludesAnnotation();
|
||||
|
||||
@SourceFilters(includes = "?0")
|
||||
Flux<SampleEntity> searchBy(Collection<String> sourceIncludes);
|
||||
|
||||
@Query("""
|
||||
{
|
||||
"match_all": {}
|
||||
}
|
||||
""")
|
||||
@SourceFilters(excludes = { "type", "keyword" })
|
||||
Flux<SampleEntity> searchWithSourceFilterExcludesAnnotation();
|
||||
|
||||
@SourceFilters(excludes = "?0")
|
||||
Flux<SampleEntity> findBy(Collection<String> sourceExcludes);
|
||||
}
|
||||
|
||||
@Document(indexName = "#{@indexNameProvider.indexName()}")
|
||||
@ -693,10 +808,15 @@ abstract class SimpleReactiveElasticsearchRepositoryIntegrationTests {
|
||||
@Field(type = FieldType.Text, store = true, fielddata = true) private String type;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Text, store = true, fielddata = true) private String message;
|
||||
@Nullable
|
||||
@Field(type = FieldType.Keyword) private String keyword;
|
||||
|
||||
@Nullable private int rate;
|
||||
@Nullable private boolean available;
|
||||
@Nullable
|
||||
@Version private Long version;
|
||||
@Field(name = "custom_field_name", type = FieldType.Text)
|
||||
@Nullable private String customFieldNameMessage;
|
||||
|
||||
public SampleEntity() {}
|
||||
|
||||
@ -733,6 +853,15 @@ abstract class SimpleReactiveElasticsearchRepositoryIntegrationTests {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getKeyword() {
|
||||
return keyword;
|
||||
}
|
||||
|
||||
public void setKeyword(@Nullable String keyword) {
|
||||
this.keyword = keyword;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getMessage() {
|
||||
return message;
|
||||
@ -766,5 +895,14 @@ abstract class SimpleReactiveElasticsearchRepositoryIntegrationTests {
|
||||
public void setVersion(@Nullable java.lang.Long version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getCustomFieldNameMessage() {
|
||||
return customFieldNameMessage;
|
||||
}
|
||||
|
||||
public void setCustomFieldNameMessage(@Nullable String customFieldNameMessage) {
|
||||
this.customFieldNameMessage = customFieldNameMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user