mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-06-14 08:02:11 +00:00
Fix repository methods value converting.
Original Pull Request #2339 Closes #2338 (cherry picked from commit e67150a55b4639405bcf49b52a6894a191805796)
This commit is contained in:
parent
edac49c470
commit
933ebab0e0
@ -40,6 +40,7 @@ import org.springframework.data.elasticsearch.core.document.SearchDocument;
|
||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
|
||||
import org.springframework.data.elasticsearch.core.mapping.PropertyValueConverter;
|
||||
import org.springframework.data.elasticsearch.core.query.BaseQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.Criteria;
|
||||
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.FetchSourceFilter;
|
||||
@ -1156,6 +1157,13 @@ public class MappingElasticsearchConverter
|
||||
|
||||
Assert.notNull(query, "query must not be null");
|
||||
|
||||
if (query instanceof BaseQuery) {
|
||||
|
||||
if (((BaseQuery) query).queryIsUpdatedByConverter()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (domainClass == null) {
|
||||
return;
|
||||
}
|
||||
@ -1165,6 +1173,10 @@ public class MappingElasticsearchConverter
|
||||
if (query instanceof CriteriaQuery) {
|
||||
updatePropertiesInCriteriaQuery((CriteriaQuery) query, domainClass);
|
||||
}
|
||||
|
||||
if (query instanceof BaseQuery) {
|
||||
((BaseQuery) query).setQueryIsUpdatedByConverter(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePropertiesInFieldsAndSourceFilter(Query query, Class<?> domainClass) {
|
||||
|
@ -73,6 +73,8 @@ public class BaseQuery implements Query {
|
||||
protected final List<RuntimeField> runtimeFields = new ArrayList<>();
|
||||
@Nullable protected List<IndexBoost> indicesBoost;
|
||||
|
||||
private boolean queryIsUpdatedByConverter = false;
|
||||
|
||||
public BaseQuery() {}
|
||||
|
||||
public <Q extends BaseQuery, B extends BaseQueryBuilder<Q, B>> BaseQuery(BaseQueryBuilder<Q, B> builder) {
|
||||
@ -440,4 +442,23 @@ public class BaseQuery implements Query {
|
||||
public List<IndexBoost> getIndicesBoost() {
|
||||
return indicesBoost;
|
||||
}
|
||||
|
||||
/**
|
||||
* used internally. Not considered part of the API.
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
public boolean queryIsUpdatedByConverter() {
|
||||
return queryIsUpdatedByConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* used internally. Not considered part of the API.
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
public void setQueryIsUpdatedByConverter(boolean queryIsUpdatedByConverter) {
|
||||
this.queryIsUpdatedByConverter = queryIsUpdatedByConverter;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,9 +15,24 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.repository.query;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
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.SearchHitsImpl;
|
||||
import org.springframework.data.elasticsearch.core.TotalHitsRelation;
|
||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.repository.query.ParametersParameterAccessor;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.data.util.StreamUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* AbstractElasticsearchRepositoryQuery
|
||||
@ -32,11 +47,13 @@ public abstract class AbstractElasticsearchRepositoryQuery implements Repository
|
||||
protected static final int DEFAULT_STREAM_BATCH_SIZE = 500;
|
||||
protected ElasticsearchQueryMethod queryMethod;
|
||||
protected 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 +66,117 @@ public abstract class AbstractElasticsearchRepositoryQuery implements Repository
|
||||
* @since 4.2
|
||||
*/
|
||||
public abstract boolean isCountQuery();
|
||||
|
||||
protected abstract boolean isDeleteQuery();
|
||||
|
||||
protected abstract boolean isExistsQuery();
|
||||
|
||||
@Override
|
||||
public Object execute(Object[] parameters) {
|
||||
|
||||
ParametersParameterAccessor parameterAccessor = getParameterAccessor(parameters);
|
||||
Class<?> clazz = getResultClass();
|
||||
Query query = createQuery(parameters);
|
||||
|
||||
IndexCoordinates index = elasticsearchOperations.getIndexCoordinatesFor(clazz);
|
||||
|
||||
Object result = null;
|
||||
|
||||
if (isDeleteQuery()) {
|
||||
result = countOrGetDocumentsForDelete(query, parameterAccessor);
|
||||
elasticsearchOperations.delete(query, clazz, index);
|
||||
elasticsearchOperations.indexOps(index).refresh();
|
||||
} else if (isCountQuery()) {
|
||||
result = elasticsearchOperations.count(query, clazz, index);
|
||||
} else if (isExistsQuery()) {
|
||||
result = elasticsearchOperations.count(query, clazz, index) > 0;
|
||||
} else if (queryMethod.isPageQuery()) {
|
||||
query.setPageable(parameterAccessor.getPageable());
|
||||
SearchHits<?> searchHits = elasticsearchOperations.search(query, clazz, index);
|
||||
if (queryMethod.isSearchPageMethod()) {
|
||||
result = SearchHitSupport.searchPageFor(searchHits, query.getPageable());
|
||||
} else {
|
||||
result = SearchHitSupport.unwrapSearchHits(SearchHitSupport.searchPageFor(searchHits, query.getPageable()));
|
||||
}
|
||||
} else if (queryMethod.isStreamQuery()) {
|
||||
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()) {
|
||||
|
||||
if (parameterAccessor.getPageable().isUnpaged()) {
|
||||
int itemCount = (int) elasticsearchOperations.count(query, clazz, index);
|
||||
|
||||
if (itemCount == 0) {
|
||||
result = new SearchHitsImpl<>(0, TotalHitsRelation.EQUAL_TO, Float.NaN, null, Collections.emptyList(), null,
|
||||
null);
|
||||
} else {
|
||||
query.setPageable(PageRequest.of(0, Math.max(1, itemCount)));
|
||||
}
|
||||
} else {
|
||||
query.setPageable(parameterAccessor.getPageable());
|
||||
}
|
||||
|
||||
if (result == null) {
|
||||
result = elasticsearchOperations.search(query, clazz, index);
|
||||
}
|
||||
|
||||
} else {
|
||||
result = elasticsearchOperations.searchOne(query, clazz, index);
|
||||
}
|
||||
|
||||
return (queryMethod.isNotSearchHitMethod() && queryMethod.isNotSearchPageMethod())
|
||||
? SearchHitSupport.unwrapSearchHits(result)
|
||||
: result;
|
||||
}
|
||||
|
||||
public Query createQuery(Object[] parameters) {
|
||||
|
||||
Class<?> clazz = getResultClass();
|
||||
ParametersParameterAccessor parameterAccessor = getParameterAccessor(parameters);
|
||||
Query query = createQuery(parameterAccessor);
|
||||
|
||||
Assert.notNull(query, "unsupported query");
|
||||
|
||||
if (queryMethod.hasAnnotatedHighlight()) {
|
||||
query.setHighlightQuery(queryMethod.getAnnotatedHighlightQuery());
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
private Class<?> getResultClass() {
|
||||
return queryMethod.getResultProcessor().getReturnedType().getDomainType();
|
||||
}
|
||||
|
||||
private ParametersParameterAccessor getParameterAccessor(Object[] parameters) {
|
||||
return new ParametersParameterAccessor(queryMethod.getParameters(), parameters);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Object countOrGetDocumentsForDelete(Query query, ParametersParameterAccessor accessor) {
|
||||
|
||||
Object result = null;
|
||||
Class<?> entityClass = queryMethod.getEntityInformation().getJavaType();
|
||||
IndexCoordinates index = elasticsearchOperations.getIndexCoordinatesFor(entityClass);
|
||||
|
||||
if (queryMethod.isCollectionQuery()) {
|
||||
|
||||
if (accessor.getPageable().isUnpaged()) {
|
||||
int itemCount = (int) elasticsearchOperations.count(query, entityClass, index);
|
||||
query.setPageable(PageRequest.of(0, Math.max(1, itemCount)));
|
||||
} else {
|
||||
query.setPageable(accessor.getPageable());
|
||||
}
|
||||
result = elasticsearchOperations.search(query, entityClass, index);
|
||||
}
|
||||
|
||||
if (ClassUtils.isAssignable(Number.class, queryMethod.getReturnedObjectType())) {
|
||||
result = elasticsearchOperations.count(query, entityClass, index);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected abstract Query createQuery(ParametersParameterAccessor accessor);
|
||||
}
|
||||
|
@ -15,26 +15,18 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.repository.query;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
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.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;
|
||||
import org.springframework.data.elasticsearch.core.query.BaseQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.elasticsearch.repository.query.parser.ElasticsearchQueryCreator;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.repository.query.ParametersParameterAccessor;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
import org.springframework.data.util.StreamUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* ElasticsearchPartQuery
|
||||
@ -49,13 +41,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();
|
||||
}
|
||||
|
||||
@ -65,106 +55,24 @@ public class ElasticsearchPartQuery extends AbstractElasticsearchRepositoryQuery
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object execute(Object[] parameters) {
|
||||
Class<?> clazz = queryMethod.getResultProcessor().getReturnedType().getDomainType();
|
||||
ParametersParameterAccessor accessor = new ParametersParameterAccessor(queryMethod.getParameters(), parameters);
|
||||
protected boolean isDeleteQuery() {
|
||||
return tree.isDelete();
|
||||
}
|
||||
|
||||
CriteriaQuery query = createQuery(accessor);
|
||||
@Override
|
||||
protected boolean isExistsQuery() {
|
||||
return tree.isExistsProjection();
|
||||
}
|
||||
|
||||
Assert.notNull(query, "unsupported query");
|
||||
protected Query createQuery(ParametersParameterAccessor accessor) {
|
||||
|
||||
elasticsearchConverter.updateQuery(query, clazz);
|
||||
|
||||
if (queryMethod.hasAnnotatedHighlight()) {
|
||||
query.setHighlightQuery(queryMethod.getAnnotatedHighlightQuery());
|
||||
}
|
||||
|
||||
IndexCoordinates index = elasticsearchOperations.getIndexCoordinatesFor(clazz);
|
||||
|
||||
Object result = null;
|
||||
BaseQuery query = new ElasticsearchQueryCreator(tree, accessor, mappingContext).createQuery();
|
||||
|
||||
if (tree.isLimiting()) {
|
||||
// noinspection ConstantConditions
|
||||
query.setMaxResults(tree.getMaxResults());
|
||||
}
|
||||
|
||||
if (tree.isDelete()) {
|
||||
result = countOrGetDocumentsForDelete(query, accessor);
|
||||
elasticsearchOperations.delete(query, clazz, index);
|
||||
elasticsearchOperations.indexOps(index).refresh();
|
||||
} else if (queryMethod.isPageQuery()) {
|
||||
query.setPageable(accessor.getPageable());
|
||||
SearchHits<?> searchHits = elasticsearchOperations.search(query, clazz, index);
|
||||
if (queryMethod.isSearchPageMethod()) {
|
||||
result = SearchHitSupport.searchPageFor(searchHits, query.getPageable());
|
||||
} else {
|
||||
result = SearchHitSupport.unwrapSearchHits(SearchHitSupport.searchPageFor(searchHits, query.getPageable()));
|
||||
}
|
||||
} else if (queryMethod.isStreamQuery()) {
|
||||
if (accessor.getPageable().isUnpaged()) {
|
||||
query.setPageable(PageRequest.of(0, DEFAULT_STREAM_BATCH_SIZE));
|
||||
} else {
|
||||
query.setPageable(accessor.getPageable());
|
||||
}
|
||||
result = StreamUtils.createStreamFromIterator(elasticsearchOperations.searchForStream(query, clazz, index));
|
||||
} else if (queryMethod.isCollectionQuery()) {
|
||||
|
||||
if (accessor.getPageable().isUnpaged()) {
|
||||
int itemCount = (int) elasticsearchOperations.count(query, clazz, index);
|
||||
|
||||
if (itemCount == 0) {
|
||||
result = new SearchHitsImpl<>(0, TotalHitsRelation.EQUAL_TO, Float.NaN, null, Collections.emptyList(), null,
|
||||
null);
|
||||
} else {
|
||||
query.setPageable(PageRequest.of(0, Math.max(1, itemCount)));
|
||||
}
|
||||
} else {
|
||||
query.setPageable(accessor.getPageable());
|
||||
}
|
||||
|
||||
if (result == null) {
|
||||
result = elasticsearchOperations.search(query, clazz, index);
|
||||
}
|
||||
|
||||
} else if (tree.isCountProjection()) {
|
||||
result = elasticsearchOperations.count(query, clazz, index);
|
||||
} else if (tree.isExistsProjection()) {
|
||||
long count = elasticsearchOperations.count(query, clazz, index);
|
||||
result = count > 0;
|
||||
} else {
|
||||
result = elasticsearchOperations.searchOne(query, clazz, index);
|
||||
}
|
||||
|
||||
return (queryMethod.isNotSearchHitMethod() && queryMethod.isNotSearchPageMethod())
|
||||
? SearchHitSupport.unwrapSearchHits(result)
|
||||
: result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Object countOrGetDocumentsForDelete(CriteriaQuery query, ParametersParameterAccessor accessor) {
|
||||
|
||||
Object result = null;
|
||||
Class<?> clazz = queryMethod.getEntityInformation().getJavaType();
|
||||
IndexCoordinates index = elasticsearchOperations.getIndexCoordinatesFor(clazz);
|
||||
|
||||
if (queryMethod.isCollectionQuery()) {
|
||||
|
||||
if (accessor.getPageable().isUnpaged()) {
|
||||
int itemCount = (int) elasticsearchOperations.count(query, clazz, index);
|
||||
query.setPageable(PageRequest.of(0, Math.max(1, itemCount)));
|
||||
} else {
|
||||
query.setPageable(accessor.getPageable());
|
||||
}
|
||||
result = elasticsearchOperations.search(query, clazz, index);
|
||||
}
|
||||
|
||||
if (ClassUtils.isAssignable(Number.class, queryMethod.getReturnedObjectType())) {
|
||||
result = elasticsearchOperations.count(query, clazz, index);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public CriteriaQuery createQuery(ParametersParameterAccessor accessor) {
|
||||
return new ElasticsearchQueryCreator(tree, accessor, mappingContext).createQuery();
|
||||
return query;
|
||||
}
|
||||
}
|
||||
|
@ -15,16 +15,11 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.repository.query;
|
||||
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
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;
|
||||
import org.springframework.data.util.StreamUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@ -38,13 +33,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
|
||||
@ -53,54 +48,20 @@ public class ElasticsearchStringQuery extends AbstractElasticsearchRepositoryQue
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object execute(Object[] parameters) {
|
||||
|
||||
Class<?> clazz = queryMethod.getResultProcessor().getReturnedType().getDomainType();
|
||||
ParametersParameterAccessor accessor = new ParametersParameterAccessor(queryMethod.getParameters(), parameters);
|
||||
|
||||
StringQuery stringQuery = createQuery(accessor);
|
||||
|
||||
Assert.notNull(stringQuery, "unsupported query");
|
||||
|
||||
if (queryMethod.hasAnnotatedHighlight()) {
|
||||
stringQuery.setHighlightQuery(queryMethod.getAnnotatedHighlightQuery());
|
||||
}
|
||||
|
||||
IndexCoordinates index = elasticsearchOperations.getIndexCoordinatesFor(clazz);
|
||||
|
||||
Object result = null;
|
||||
|
||||
if (isCountQuery()) {
|
||||
result = elasticsearchOperations.count(stringQuery, clazz, index);
|
||||
} else if (queryMethod.isPageQuery()) {
|
||||
stringQuery.setPageable(accessor.getPageable());
|
||||
SearchHits<?> searchHits = elasticsearchOperations.search(stringQuery, clazz, index);
|
||||
if (queryMethod.isSearchPageMethod()) {
|
||||
result = SearchHitSupport.searchPageFor(searchHits, stringQuery.getPageable());
|
||||
} else {
|
||||
result = SearchHitSupport
|
||||
.unwrapSearchHits(SearchHitSupport.searchPageFor(searchHits, stringQuery.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));
|
||||
} else if (queryMethod.isCollectionQuery()) {
|
||||
stringQuery.setPageable(accessor.getPageable().isPaged() ? accessor.getPageable() : Pageable.unpaged());
|
||||
result = elasticsearchOperations.search(stringQuery, clazz, index);
|
||||
} else {
|
||||
result = elasticsearchOperations.searchOne(stringQuery, clazz, index);
|
||||
}
|
||||
|
||||
return (queryMethod.isNotSearchHitMethod() && queryMethod.isNotSearchPageMethod())
|
||||
? SearchHitSupport.unwrapSearchHits(result)
|
||||
: result;
|
||||
protected boolean isDeleteQuery() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected StringQuery createQuery(ParametersParameterAccessor parameterAccessor) {
|
||||
@Override
|
||||
protected boolean isExistsQuery() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected Query createQuery(ParametersParameterAccessor parameterAccessor) {
|
||||
|
||||
String queryString = new StringQueryUtil(elasticsearchOperations.getElasticsearchConverter().getConversionService())
|
||||
.replacePlaceholders(this.query, parameterAccessor);
|
||||
.replacePlaceholders(this.queryString, parameterAccessor);
|
||||
|
||||
return new StringQuery(queryString);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -61,7 +61,6 @@ final public class StringQueryUtil {
|
||||
String parameterValue = "null";
|
||||
|
||||
if (parameter != null) {
|
||||
|
||||
parameterValue = convert(parameter);
|
||||
}
|
||||
|
||||
|
@ -21,8 +21,8 @@ import co.elastic.clients.json.jackson.JacksonJsonpMapper;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.ElasticsearchPartQueryIntegrationTests;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchTemplateConfiguration;
|
||||
|
||||
/**
|
||||
@ -36,12 +36,11 @@ public class ElasticsearchPartQueryELCIntegrationTests extends ElasticsearchPart
|
||||
static class Config {}
|
||||
|
||||
@Override
|
||||
protected String buildQueryString(CriteriaQuery criteriaQuery, Class<?> clazz) {
|
||||
protected String buildQueryString(Query query, Class<?> clazz) {
|
||||
|
||||
JacksonJsonpMapper jsonpMapper = new JacksonJsonpMapper();
|
||||
RequestConverter requestConverter = new RequestConverter(operations.getElasticsearchConverter(), jsonpMapper);
|
||||
SearchRequest request = requestConverter.searchRequest(criteriaQuery, clazz, IndexCoordinates.of("dummy"), false,
|
||||
false);
|
||||
SearchRequest request = requestConverter.searchRequest(query, clazz, IndexCoordinates.of("dummy"), false, false);
|
||||
|
||||
return JsonUtils.toJson(request, jsonpMapper);
|
||||
// return "{\"query\":" + JsonUtils.toJson(request.query(), jsonpMapper) + "}";
|
||||
|
@ -19,8 +19,8 @@ import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.ElasticsearchPartQueryIntegrationTests;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchRestTemplateConfiguration;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
@ -38,9 +38,9 @@ public class ElasticsearchPartQueryERHLCIntegrationTests extends ElasticsearchPa
|
||||
@Import({ ElasticsearchRestTemplateConfiguration.class })
|
||||
static class Config {}
|
||||
|
||||
protected String buildQueryString(CriteriaQuery criteriaQuery, Class<?> clazz) {
|
||||
protected String buildQueryString(Query query, Class<?> clazz) {
|
||||
SearchSourceBuilder source = new RequestFactory(operations.getElasticsearchConverter())
|
||||
.searchRequest(criteriaQuery, clazz, IndexCoordinates.of("dummy")).source();
|
||||
.searchRequest(query, clazz, IndexCoordinates.of("dummy")).source();
|
||||
// remove defaultboost values
|
||||
return source.toString().replaceAll("(\\^\\d+\\.\\d+)", "");
|
||||
}
|
||||
|
@ -36,7 +36,6 @@ import org.springframework.data.elasticsearch.repository.query.ElasticsearchPart
|
||||
import org.springframework.data.elasticsearch.repository.query.ElasticsearchQueryMethod;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
|
||||
import org.springframework.data.repository.query.ParametersParameterAccessor;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
@ -637,19 +636,18 @@ public abstract class ElasticsearchPartQueryIntegrationTests {
|
||||
new DefaultRepositoryMetadata(SampleRepository.class), new SpelAwareProxyProjectionFactory(),
|
||||
operations.getElasticsearchConverter().getMappingContext());
|
||||
ElasticsearchPartQuery partQuery = new ElasticsearchPartQuery(queryMethod, operations);
|
||||
CriteriaQuery criteriaQuery = partQuery
|
||||
.createQuery(new ParametersParameterAccessor(queryMethod.getParameters(), parameters));
|
||||
return buildQueryString(criteriaQuery, Book.class);
|
||||
Query query = partQuery.createQuery(parameters);
|
||||
return buildQueryString(query, Book.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* builds the query String that would be sent to Elasticsearch
|
||||
*
|
||||
* @param criteriaQuery the {@link CriteriaQuery}
|
||||
* @param query the {@link Query}
|
||||
* @param clazz the entity class
|
||||
* @return the created query string
|
||||
*/
|
||||
abstract protected String buildQueryString(CriteriaQuery criteriaQuery, Class<?> clazz);
|
||||
abstract protected String buildQueryString(Query query, Class<?> clazz);
|
||||
|
||||
@FunctionalInterface
|
||||
interface AssertFunction {
|
||||
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.repository.query.valueconverter;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ReactiveElasticsearchTemplateConfiguration;
|
||||
import org.springframework.data.elasticsearch.repository.config.EnableReactiveElasticsearchRepositories;
|
||||
import org.springframework.data.elasticsearch.utils.IndexNameProvider;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
/**
|
||||
* @author Peter-Josef Meisch
|
||||
* @since 5.0
|
||||
*/
|
||||
@ContextConfiguration(classes = { ReactiveValueConverterELCIntegrationTests.Config.class })
|
||||
public class ReactiveValueConverterELCIntegrationTests extends ReactiveValueConverterIntegrationTests {
|
||||
|
||||
@Configuration
|
||||
@Import({ ReactiveElasticsearchTemplateConfiguration.class })
|
||||
@EnableReactiveElasticsearchRepositories(considerNestedRepositories = true)
|
||||
static class Config {
|
||||
@Bean
|
||||
IndexNameProvider indexNameProvider() {
|
||||
return new IndexNameProvider("reactive-valueconverter");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.repository.query.valueconverter;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ReactiveElasticsearchRestTemplateConfiguration;
|
||||
import org.springframework.data.elasticsearch.repository.config.EnableReactiveElasticsearchRepositories;
|
||||
import org.springframework.data.elasticsearch.utils.IndexNameProvider;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
/**
|
||||
* @author Peter-Josef Meisch
|
||||
* @since 5.0
|
||||
*/
|
||||
@ContextConfiguration(classes = { ReactiveValueConverterERHLCIntegrationTests.Config.class })
|
||||
public class ReactiveValueConverterERHLCIntegrationTests extends ReactiveValueConverterIntegrationTests {
|
||||
|
||||
@Configuration
|
||||
@Import({ ReactiveElasticsearchRestTemplateConfiguration.class })
|
||||
@EnableReactiveElasticsearchRepositories(considerNestedRepositories = true)
|
||||
static class Config {
|
||||
@Bean
|
||||
IndexNameProvider indexNameProvider() {
|
||||
return new IndexNameProvider("reactive-valueconverter-es7");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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.repository.query.valueconverter;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.data.elasticsearch.annotations.FieldType.*;
|
||||
|
||||
import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||
import org.springframework.data.elasticsearch.annotations.Query;
|
||||
import org.springframework.data.elasticsearch.annotations.ValueConverter;
|
||||
import org.springframework.data.elasticsearch.core.SearchHits;
|
||||
import org.springframework.data.elasticsearch.core.mapping.PropertyValueConverter;
|
||||
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.lang.Boolean;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.SearchHit;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest;
|
||||
import org.springframework.data.elasticsearch.repository.ReactiveElasticsearchRepository;
|
||||
import org.springframework.data.elasticsearch.utils.IndexNameProvider;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Integration tests to check that {@link org.springframework.data.elasticsearch.annotations.ValueConverter} annotated
|
||||
* properties are handle correctly (method name derived queries, for
|
||||
*
|
||||
* @{@link org.springframework.data.elasticsearch.core.query.Query} methods we don't know which parameters map to which
|
||||
* property.
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
@SpringIntegrationTest
|
||||
public abstract class ReactiveValueConverterIntegrationTests {
|
||||
|
||||
@Autowired private IndexNameProvider indexNameProvider;
|
||||
@Autowired private ReactiveElasticsearchOperations operations;
|
||||
@Autowired private EntityRepository repository;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
indexNameProvider.increment();
|
||||
operations.indexOps(Entity.class).createWithMapping().block();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(java.lang.Integer.MAX_VALUE)
|
||||
void cleanup() {
|
||||
operations.indexOps(IndexCoordinates.of(indexNameProvider.getPrefix() + '*')).delete().block();
|
||||
}
|
||||
|
||||
|
||||
@Test // #2338
|
||||
@DisplayName("should apply ValueConverter")
|
||||
void shouldApplyValueConverter() {
|
||||
|
||||
ValueConverterIntegrationTests.Entity entity = new ValueConverterIntegrationTests.Entity();
|
||||
entity.setId("42");
|
||||
entity.setText("answer");
|
||||
operations.save(entity).block();
|
||||
|
||||
repository.queryByText("text-answer") //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(1) //
|
||||
.verifyComplete();
|
||||
|
||||
repository.findByText("answer") //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(1) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
interface EntityRepository extends ReactiveElasticsearchRepository<Entity, String> {
|
||||
Flux<SearchHit<Entity>> findByText(String text);
|
||||
|
||||
@Query("{ \"term\": { \"text\": \"?0\" } }")
|
||||
Flux<SearchHit<Entity>> queryByText(String text);
|
||||
}
|
||||
|
||||
@Document(indexName = "#{@indexNameProvider.indexName()}")
|
||||
static class Entity {
|
||||
@Id
|
||||
@Nullable private String id;
|
||||
|
||||
@Field(type = FieldType.Keyword)
|
||||
@ValueConverter(ValueConverterIntegrationTests.TextConverter.class)
|
||||
@Nullable private String text;
|
||||
|
||||
@Nullable
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(@Nullable String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(@Nullable String text) {
|
||||
this.text = text;
|
||||
}
|
||||
}
|
||||
|
||||
static class TextConverter implements PropertyValueConverter {
|
||||
|
||||
public static final String PREFIX = "text-";
|
||||
|
||||
@Override
|
||||
public Object write(Object value) {
|
||||
return PREFIX + value.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(Object value) {
|
||||
|
||||
String valueString = value.toString();
|
||||
|
||||
if (valueString.startsWith(PREFIX)) {
|
||||
return valueString.substring(PREFIX.length());
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.repository.query.valueconverter;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchTemplateConfiguration;
|
||||
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
|
||||
import org.springframework.data.elasticsearch.utils.IndexNameProvider;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
/**
|
||||
* {@link ValueConverterIntegrationTests} using a Repository backed by an ElasticsearchTemplate.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
* @since 5.0
|
||||
*/
|
||||
@ContextConfiguration(classes = { ValueConverterELCIntegrationTests.Config.class })
|
||||
public class ValueConverterELCIntegrationTests extends ValueConverterIntegrationTests {
|
||||
|
||||
@Configuration
|
||||
@Import({ ElasticsearchTemplateConfiguration.class })
|
||||
@EnableElasticsearchRepositories(considerNestedRepositories = true)
|
||||
static class Config {
|
||||
@Bean
|
||||
IndexNameProvider indexNameProvider() {
|
||||
return new IndexNameProvider("valueconverter");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.repository.query.valueconverter;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchRestTemplateConfiguration;
|
||||
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
|
||||
import org.springframework.data.elasticsearch.utils.IndexNameProvider;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
/**
|
||||
* {@link ValueConverterIntegrationTests} using a Repository backed by an ElasticsearchTemplate.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
* @since 5.0
|
||||
*/
|
||||
@ContextConfiguration(classes = { ValueConverterERHLCIntegrationTests.Config.class })
|
||||
public class ValueConverterERHLCIntegrationTests extends ValueConverterIntegrationTests {
|
||||
|
||||
@Configuration
|
||||
@Import({ ElasticsearchRestTemplateConfiguration.class })
|
||||
@EnableElasticsearchRepositories(considerNestedRepositories = true)
|
||||
static class Config {
|
||||
@Bean
|
||||
IndexNameProvider indexNameProvider() {
|
||||
return new IndexNameProvider("valueconverter-es7");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* 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.repository.query.valueconverter;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||
import org.springframework.data.elasticsearch.annotations.Query;
|
||||
import org.springframework.data.elasticsearch.annotations.ValueConverter;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.SearchHits;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.mapping.PropertyValueConverter;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest;
|
||||
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
|
||||
import org.springframework.data.elasticsearch.utils.IndexNameProvider;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Integration tests to check that {@link org.springframework.data.elasticsearch.annotations.ValueConverter} annotated
|
||||
* properties are handle correctly (method name derived queries, for
|
||||
*
|
||||
* @{@link org.springframework.data.elasticsearch.core.query.Query} methods we don't know which parameters map to which
|
||||
* property.
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
@SpringIntegrationTest
|
||||
abstract class ValueConverterIntegrationTests {
|
||||
|
||||
@Autowired private EntityRepository repository;
|
||||
@Autowired ElasticsearchOperations operations;
|
||||
@Autowired IndexNameProvider indexNameProvider;
|
||||
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
indexNameProvider.increment();
|
||||
operations.indexOps(Entity.class).createWithMapping();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(Integer.MAX_VALUE)
|
||||
void cleanup() {
|
||||
operations.indexOps(IndexCoordinates.of(indexNameProvider.getPrefix() + '*')).delete();
|
||||
}
|
||||
|
||||
@Test // #2338
|
||||
@DisplayName("should apply ValueConverter")
|
||||
void shouldApplyValueConverter() {
|
||||
|
||||
Entity entity = new Entity();
|
||||
entity.setId("42");
|
||||
entity.setText("answer");
|
||||
operations.save(entity);
|
||||
|
||||
SearchHits<Entity> searchHits = repository.queryByText("text-answer");
|
||||
assertThat(searchHits.getTotalHits()).isEqualTo(1);
|
||||
|
||||
searchHits = repository.findByText("answer");
|
||||
assertThat(searchHits.getTotalHits()).isEqualTo(1);
|
||||
}
|
||||
|
||||
interface EntityRepository extends ElasticsearchRepository<Entity, String> {
|
||||
SearchHits<Entity> findByText(String text);
|
||||
|
||||
@Query("{ \"term\": { \"text\": \"?0\" } }")
|
||||
SearchHits<Entity> queryByText(String text);
|
||||
}
|
||||
|
||||
@Document(indexName = "#{@indexNameProvider.indexName()}")
|
||||
static class Entity {
|
||||
@Id
|
||||
@Nullable private String id;
|
||||
|
||||
@Field(type = FieldType.Keyword)
|
||||
@ValueConverter(TextConverter.class)
|
||||
@Nullable private String text;
|
||||
|
||||
@Nullable
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(@Nullable String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(@Nullable String text) {
|
||||
this.text = text;
|
||||
}
|
||||
}
|
||||
|
||||
static class TextConverter implements PropertyValueConverter {
|
||||
|
||||
public static final String PREFIX = "text-";
|
||||
|
||||
@Override
|
||||
public Object write(Object value) {
|
||||
return PREFIX + value.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(Object value) {
|
||||
|
||||
String valueString = value.toString();
|
||||
|
||||
if (valueString.startsWith(PREFIX)) {
|
||||
return valueString.substring(PREFIX.length());
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user