DATAES-630 - Remove GetResultMapper and friends from core package.

Original PR: #331
This commit is contained in:
Peter-Josef Meisch 2019-10-25 22:05:58 +02:00 committed by GitHub
parent d4f23a50e7
commit 4e7f1ccb4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 600 additions and 2004 deletions

View File

@ -19,8 +19,7 @@ import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.ResultsMapper;
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
/**
* @author Christoph Strobl
@ -45,8 +44,7 @@ public abstract class AbstractElasticsearchConfiguration extends ElasticsearchCo
* @return never {@literal null}.
*/
@Bean(name = { "elasticsearchOperations", "elasticsearchTemplate" })
public ElasticsearchOperations elasticsearchOperations(MappingElasticsearchConverter mappingElasticsearchConverter,
ResultsMapper resultsMapper) {
return new ElasticsearchRestTemplate(elasticsearchClient(), mappingElasticsearchConverter, resultsMapper);
public ElasticsearchOperations elasticsearchOperations(ElasticsearchConverter elasticsearchConverter) {
return new ElasticsearchRestTemplate(elasticsearchClient(), elasticsearchConverter);
}
}

View File

@ -22,12 +22,12 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient;
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations;
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.ResultsMapper;
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.springframework.lang.Nullable;
/**
* @author Christoph Strobl
* @author Peter-Josef Meisch
* @since 3.2
* @see ElasticsearchConfigurationSupport
*/
@ -49,11 +49,10 @@ public abstract class AbstractReactiveElasticsearchConfiguration extends Elastic
* @return never {@literal null}.
*/
@Bean
public ReactiveElasticsearchOperations reactiveElasticsearchTemplate(
MappingElasticsearchConverter mappingElasticsearchConverter, ResultsMapper resultsMapper) {
public ReactiveElasticsearchOperations reactiveElasticsearchTemplate(ElasticsearchConverter elasticsearchConverter) {
ReactiveElasticsearchTemplate template = new ReactiveElasticsearchTemplate(reactiveElasticsearchClient(),
mappingElasticsearchConverter, resultsMapper);
elasticsearchConverter);
template.setIndicesOptions(indicesOptions());
template.setRefreshPolicy(refreshPolicy());

View File

@ -27,13 +27,10 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.data.annotation.Persistent;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.core.DefaultResultMapper;
import org.springframework.data.elasticsearch.core.EntityMapper;
import org.springframework.data.elasticsearch.core.ResultsMapper;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchCustomConversions;
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
@ -49,7 +46,7 @@ import org.springframework.util.StringUtils;
public class ElasticsearchConfigurationSupport {
@Bean
public MappingElasticsearchConverter elasticsearchEntityMapper(
public ElasticsearchConverter elasticsearchEntityMapper(
SimpleElasticsearchMappingContext elasticsearchMappingContext) {
return new MappingElasticsearchConverter(elasticsearchMappingContext);
}
@ -72,17 +69,6 @@ public class ElasticsearchConfigurationSupport {
return mappingContext;
}
/**
* Returns the {@link ResultsMapper} to be used for search responses.
*
* @see MappingElasticsearchConverter
* @return never {@literal null}.
*/
@Bean
public ResultsMapper resultsMapper(SimpleElasticsearchMappingContext elasticsearchMappingContext) {
return new DefaultResultMapper(elasticsearchMappingContext, elasticsearchEntityMapper(elasticsearchMappingContext));
}
/**
* Register custom {@link Converter}s in a {@link ElasticsearchCustomConversions} object if required.
*

View File

@ -5,20 +5,30 @@ import org.slf4j.LoggerFactory;
import org.springframework.data.elasticsearch.ElasticsearchException;
import org.springframework.data.elasticsearch.annotations.Mapping;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
import org.springframework.data.elasticsearch.core.index.MappingBuilder;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
import org.springframework.util.StringUtils;
/**
* AbstractElasticsearchTemplate
*
* @author Sascha Woo
* @author Peter-Josef Meisch
*/
public abstract class AbstractElasticsearchTemplate {
public abstract class AbstractElasticsearchTemplate implements ElasticsearchOperations {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractElasticsearchTemplate.class);
protected ElasticsearchConverter elasticsearchConverter;
protected ElasticsearchConverter createElasticsearchConverter() {
MappingElasticsearchConverter mappingElasticsearchConverter = new MappingElasticsearchConverter(
new SimpleElasticsearchMappingContext());
mappingElasticsearchConverter.afterPropertiesSet();
return mappingElasticsearchConverter;
}
protected String buildMapping(Class<?> clazz) {
// load mapping specified in Mapping annotation if present
@ -43,4 +53,8 @@ public abstract class AbstractElasticsearchTemplate {
}
}
@Override
public ElasticsearchConverter getElasticsearchConverter() {
return elasticsearchConverter;
}
}

View File

@ -1,73 +0,0 @@
/*
* Copyright 2014-2019 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.core;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
import org.springframework.util.Assert;
/**
* @author Artur Konczak
* @author Christoph Strobl
*/
public abstract class AbstractResultMapper implements ResultsMapper {
private final EntityMapper entityMapper;
private final ProjectionFactory projectionFactory;
/**
* Create a new {@link AbstractResultMapper}.
*
* @param entityMapper must not be {@literal null}.
*/
public AbstractResultMapper(EntityMapper entityMapper) {
this(entityMapper, new SpelAwareProxyProjectionFactory());
}
/**
* Create a new {@link AbstractResultMapper}.
*
* @param entityMapper must not be {@literal null}.
* @param projectionFactory must not be {@literal null}.
* @since 3.2
*/
public AbstractResultMapper(EntityMapper entityMapper, ProjectionFactory projectionFactory) {
Assert.notNull(entityMapper, "EntityMapper must not be null!");
Assert.notNull(projectionFactory, "ProjectionFactory must not be null!");
this.entityMapper = entityMapper;
this.projectionFactory = projectionFactory;
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.core.ResultsMapper#getEntityMapper()
*/
@Override
public EntityMapper getEntityMapper() {
return this.entityMapper;
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.core.ResultsMapper#getProjectionFactory()
*/
@Override
public ProjectionFactory getProjectionFactory() {
return this.projectionFactory;
}
}

View File

@ -1,217 +0,0 @@
/*
* Copyright 2014-2019 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.core;
import java.util.ArrayList;
import java.util.List;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.get.MultiGetItemResponse;
import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.document.DocumentField;
import org.elasticsearch.search.SearchHit;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.ElasticsearchException;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.ScriptedField;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
import org.springframework.data.elasticsearch.support.SearchHitsUtil;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* @author Artur Konczak
* @author Petar Tahchiev
* @author Young Gu
* @author Oliver Gierke
* @author Chris White
* @author Mark Paluch
* @author Ilkang Na
* @author Sascha Woo
* @author Christoph Strobl
* @author Dmitriy Yakovlev
*/
public class DefaultResultMapper extends AbstractResultMapper {
private final MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext;
private final ConversionService conversionService = new DefaultConversionService();
public DefaultResultMapper() {
this(new SimpleElasticsearchMappingContext());
}
public DefaultResultMapper(
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext) {
this(mappingContext, null);
}
public DefaultResultMapper(EntityMapper entityMapper) {
this(new SimpleElasticsearchMappingContext(), entityMapper);
}
public DefaultResultMapper(
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext,
@Nullable EntityMapper entityMapper) {
super(entityMapper != null ? entityMapper : initEntityMapper(mappingContext));
this.mappingContext = mappingContext;
}
private static EntityMapper initEntityMapper(
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext) {
Assert.notNull(mappingContext, "MappingContext must not be null!");
MappingElasticsearchConverter mappingElasticsearchConverter = new MappingElasticsearchConverter(mappingContext, null);
mappingElasticsearchConverter.afterPropertiesSet();
return mappingElasticsearchConverter;
}
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
long totalHits = SearchHitsUtil.getTotalCount(response.getHits());
float maxScore = response.getHits().getMaxScore();
List<T> results = new ArrayList<>();
for (SearchHit hit : response.getHits()) {
if (hit != null) {
T result = mapSearchHit(hit, clazz);
setPersistentEntityId(result, hit.getId(), clazz);
setPersistentEntityVersion(result, hit.getVersion(), clazz);
setPersistentEntityScore(result, hit.getScore(), clazz);
populateScriptFields(result, hit);
results.add(result);
}
}
return new AggregatedPageImpl<T>(results, pageable, totalHits, response.getAggregations(), response.getScrollId(),
maxScore);
}
private <T> void populateScriptFields(T result, SearchHit hit) {
if (hit.getFields() != null && !hit.getFields().isEmpty() && result != null) {
for (java.lang.reflect.Field field : result.getClass().getDeclaredFields()) {
ScriptedField scriptedField = field.getAnnotation(ScriptedField.class);
if (scriptedField != null) {
String name = scriptedField.name().isEmpty() ? field.getName() : scriptedField.name();
DocumentField searchHitField = hit.getFields().get(name);
if (searchHitField != null) {
field.setAccessible(true);
try {
field.set(result, searchHitField.getValue());
} catch (IllegalArgumentException e) {
throw new ElasticsearchException(
"failed to set scripted field: " + name + " with value: " + searchHitField.getValue(), e);
} catch (IllegalAccessException e) {
throw new ElasticsearchException("failed to access scripted field: " + name, e);
}
}
}
}
}
}
@Override
public <T> T mapResult(GetResponse response, Class<T> clazz) {
if (!response.isExists()) {
return null;
}
T result = mapDocument(DocumentAdapters.from(response), clazz);
if (result != null) {
setPersistentEntityId(result, response.getId(), clazz);
setPersistentEntityVersion(result, response.getVersion(), clazz);
}
return result;
}
@Override
public <T> List<T> mapResults(MultiGetResponse responses, Class<T> clazz) {
List<T> list = new ArrayList<>();
for (MultiGetItemResponse response : responses.getResponses()) {
if (!response.isFailed() && response.getResponse().isExists()) {
T result = mapResult(response.getResponse(), clazz);
setPersistentEntityId(result, response.getResponse().getId(), clazz);
setPersistentEntityVersion(result, response.getResponse().getVersion(), clazz);
list.add(result);
}
}
return list;
}
private <T> void setPersistentEntityId(T result, String id, Class<T> clazz) {
if (clazz.isAnnotationPresent(Document.class)) {
ElasticsearchPersistentEntity<?> persistentEntity = mappingContext.getRequiredPersistentEntity(clazz);
ElasticsearchPersistentProperty idProperty = persistentEntity.getIdProperty();
PersistentPropertyAccessor<T> accessor = new ConvertingPropertyAccessor<>(
persistentEntity.getPropertyAccessor(result), conversionService);
// Only deal with String because ES generated Ids are strings !
if (idProperty != null && idProperty.getType().isAssignableFrom(String.class)) {
accessor.setProperty(idProperty, id);
}
}
}
private <T> void setPersistentEntityVersion(T result, long version, Class<T> clazz) {
if (clazz.isAnnotationPresent(Document.class)) {
ElasticsearchPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(clazz);
ElasticsearchPersistentProperty versionProperty = persistentEntity.getVersionProperty();
// Only deal with Long because ES versions are longs !
if (versionProperty != null && versionProperty.getType().isAssignableFrom(Long.class)) {
// check that a version was actually returned in the response, -1 would indicate that
// a search didn't request the version ids in the response, which would be an issue
Assert.isTrue(version != -1, "Version in response is -1");
persistentEntity.getPropertyAccessor(result).setProperty(versionProperty, version);
}
}
}
private <T> void setPersistentEntityScore(T result, float score, Class<T> clazz) {
if (clazz.isAnnotationPresent(Document.class)) {
ElasticsearchPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(clazz);
if (!entity.hasScoreProperty()) {
return;
}
entity.getPropertyAccessor(result) //
.setProperty(entity.getScoreProperty(), score);
}
}
}

View File

@ -109,7 +109,7 @@ public interface ElasticsearchOperations {
*
* @param indexName
* @param type
* @param mappings
* @param clazz
* @since 3.2
*/
<T> boolean putMapping(String indexName, String type, Class<T> clazz);
@ -180,16 +180,6 @@ public interface ElasticsearchOperations {
*/
<T> T queryForObject(GetQuery query, Class<T> clazz);
/**
* Execute the query against elasticsearch and return the first returned object using custom mapper
*
* @param query
* @param clazz
* @param mapper
* @return the first matching object
*/
<T> T queryForObject(GetQuery query, Class<T> clazz, GetResultMapper mapper);
/**
* Execute the query against elasticsearch and return the first returned object
*
@ -217,15 +207,6 @@ public interface ElasticsearchOperations {
*/
<T> Page<T> queryForPage(SearchQuery query, Class<T> clazz);
/**
* Execute the query against elasticsearch and return result as {@link Page} using custom mapper
*
* @param query
* @param clazz
* @return
*/
<T> Page<T> queryForPage(SearchQuery query, Class<T> clazz, SearchResultMapper mapper);
/**
* Execute the multi-search against elasticsearch and return result as {@link List} of {@link Page}
*
@ -235,16 +216,6 @@ public interface ElasticsearchOperations {
*/
<T> List<Page<T>> queryForPage(List<SearchQuery> queries, Class<T> clazz);
/**
* Execute the multi-search against elasticsearch and return result as {@link List} of {@link Page} using custom
* mapper
*
* @param queries
* @param clazz
* @return
*/
<T> List<Page<T>> queryForPage(List<SearchQuery> queries, Class<T> clazz, SearchResultMapper mapper);
/**
* Execute the multi-search against elasticsearch and return result as {@link List} of {@link Page}
*
@ -254,16 +225,6 @@ public interface ElasticsearchOperations {
*/
List<Page<?>> queryForPage(List<SearchQuery> queries, List<Class<?>> classes);
/**
* Execute the multi-search against elasticsearch and return result as {@link List} of {@link Page} using custom
* mapper
*
* @param queries
* @param classes
* @return
*/
List<Page<?>> queryForPage(List<SearchQuery> queries, List<Class<?>> classes, SearchResultMapper mapper);
/**
* Execute the query against elasticsearch and return result as {@link Page}
*
@ -282,15 +243,6 @@ public interface ElasticsearchOperations {
*/
<T> Page<T> queryForPage(StringQuery query, Class<T> clazz);
/**
* Execute the query against elasticsearch and return result as {@link Page} using custom mapper
*
* @param query
* @param clazz
* @return
*/
<T> Page<T> queryForPage(StringQuery query, Class<T> clazz, SearchResultMapper mapper);
/**
* Executes the given {@link CriteriaQuery} against elasticsearch and return result as {@link CloseableIterator}.
* <p>
@ -319,22 +271,6 @@ public interface ElasticsearchOperations {
*/
<T> CloseableIterator<T> stream(SearchQuery query, Class<T> clazz);
/**
* Executes the given {@link SearchQuery} against elasticsearch and return result as {@link CloseableIterator} using
* custom mapper.
* <p>
* Returns a {@link CloseableIterator} that wraps an Elasticsearch scroll context that needs to be closed in case of
* error.
*
* @param <T> element return type
* @param query
* @param clazz
* @param mapper
* @return
* @since 1.3
*/
<T> CloseableIterator<T> stream(SearchQuery query, Class<T> clazz, SearchResultMapper mapper);
/**
* Execute the criteria query against elasticsearch and return result as {@link List}
*
@ -439,16 +375,6 @@ public interface ElasticsearchOperations {
*/
<T> List<T> multiGet(SearchQuery searchQuery, Class<T> clazz);
/**
* Execute a multiGet against elasticsearch for the given ids with MultiGetResultMapper
*
* @param searchQuery
* @param clazz
* @param multiGetResultMapper
* @return
*/
<T> List<T> multiGet(SearchQuery searchQuery, Class<T> clazz, MultiGetResultMapper multiGetResultMapper);
/**
* Index an object. Will do save or update
*
@ -611,18 +537,6 @@ public interface ElasticsearchOperations {
*/
<T> ScrolledPage<T> startScroll(long scrollTimeInMillis, SearchQuery query, Class<T> clazz);
/**
* Returns scrolled page for given query
*
* @param query The search query.
* @param scrollTimeInMillis The time in millisecond for scroll feature
* {@link org.elasticsearch.action.search.SearchRequestBuilder#setScroll(org.elasticsearch.common.unit.TimeValue)}.
* @param mapper Custom impl to map result to entities
* @return The scan id for input query.
*/
<T> ScrolledPage<T> startScroll(long scrollTimeInMillis, SearchQuery query, Class<T> clazz,
SearchResultMapper mapper);
/**
* Returns scrolled page for given query
*
@ -634,23 +548,8 @@ public interface ElasticsearchOperations {
*/
<T> ScrolledPage<T> startScroll(long scrollTimeInMillis, CriteriaQuery criteriaQuery, Class<T> clazz);
/**
* Returns scrolled page for given query
*
* @param criteriaQuery The search query.
* @param scrollTimeInMillis The time in millisecond for scroll feature
* {@link org.elasticsearch.action.search.SearchRequestBuilder#setScroll(org.elasticsearch.common.unit.TimeValue)}.
* @param mapper Custom impl to map result to entities
* @return The scan id for input query.
*/
<T> ScrolledPage<T> startScroll(long scrollTimeInMillis, CriteriaQuery criteriaQuery, Class<T> clazz,
SearchResultMapper mapper);
<T> ScrolledPage<T> continueScroll(@Nullable String scrollId, long scrollTimeInMillis, Class<T> clazz);
<T> ScrolledPage<T> continueScroll(@Nullable String scrollId, long scrollTimeInMillis, Class<T> clazz,
SearchResultMapper mapper);
/**
* Clears the search contexts associated with specified scroll ids.
*

View File

@ -99,11 +99,11 @@ import org.springframework.data.elasticsearch.annotations.Setting;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.client.support.AliasData;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
import org.springframework.data.elasticsearch.core.document.DocumentAdapters;
import org.springframework.data.elasticsearch.core.document.SearchDocumentResponse;
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.data.elasticsearch.support.SearchHitsUtil;
import org.springframework.data.util.CloseableIterator;
@ -147,53 +147,28 @@ import com.fasterxml.jackson.databind.ObjectMapper;
* @author Gyula Attila Csorogi
*/
public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate
implements ElasticsearchOperations, EsClient<RestHighLevelClient>, ApplicationContextAware {
implements EsClient<RestHighLevelClient>, ApplicationContextAware {
private static final Logger logger = LoggerFactory.getLogger(ElasticsearchRestTemplate.class);
private RestHighLevelClient client;
private ResultsMapper resultsMapper;
private String searchTimeout;
public ElasticsearchRestTemplate(RestHighLevelClient client) {
MappingElasticsearchConverter mappingElasticsearchConverter = createElasticsearchConverter();
initialize(client, mappingElasticsearchConverter,
new DefaultResultMapper(mappingElasticsearchConverter.getMappingContext()));
}
public ElasticsearchRestTemplate(RestHighLevelClient client, ElasticsearchConverter elasticsearchConverter,
EntityMapper entityMapper) {
initialize(client, elasticsearchConverter,
new DefaultResultMapper(elasticsearchConverter.getMappingContext(), entityMapper));
}
public ElasticsearchRestTemplate(RestHighLevelClient client, ResultsMapper resultsMapper) {
initialize(client, createElasticsearchConverter(), resultsMapper);
initialize(client, createElasticsearchConverter());
}
public ElasticsearchRestTemplate(RestHighLevelClient client, ElasticsearchConverter elasticsearchConverter) {
initialize(client, elasticsearchConverter, new DefaultResultMapper(elasticsearchConverter.getMappingContext()));
initialize(client, elasticsearchConverter);
}
public ElasticsearchRestTemplate(RestHighLevelClient client, ElasticsearchConverter elasticsearchConverter,
ResultsMapper resultsMapper) {
initialize(client, elasticsearchConverter, resultsMapper);
}
private MappingElasticsearchConverter createElasticsearchConverter() {
return new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext());
}
private void initialize(RestHighLevelClient client, ElasticsearchConverter elasticsearchConverter,
ResultsMapper resultsMapper) {
private void initialize(RestHighLevelClient client, ElasticsearchConverter elasticsearchConverter) {
Assert.notNull(client, "Client must not be null!");
Assert.notNull(elasticsearchConverter, "elasticsearchConverter must not be null.");
Assert.notNull(resultsMapper, "ResultsMapper must not be null!");
Assert.notNull(elasticsearchConverter, "ElasticsearchConverter must not be null.");
this.client = client;
this.elasticsearchConverter = elasticsearchConverter;
this.resultsMapper = resultsMapper;
}
@Override
@ -342,25 +317,15 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate
}
@Override
public ElasticsearchConverter getElasticsearchConverter() {
return elasticsearchConverter;
}
@Override
public <T> T queryForObject(GetQuery query, Class<T> clazz) {
return queryForObject(query, clazz, resultsMapper);
}
@Override
public <T> T queryForObject(GetQuery query, Class<T> clazz, GetResultMapper mapper) {
ElasticsearchPersistentEntity<T> persistentEntity = getPersistentEntityFor(clazz);
GetRequest request = new GetRequest(persistentEntity.getIndexName(), persistentEntity.getIndexType(),
query.getId());
GetResponse response;
try {
response = client.get(request, RequestOptions.DEFAULT);
return mapper.mapResult(response, clazz);
return elasticsearchConverter.mapDocument(DocumentAdapters.from(response), clazz);
} catch (IOException e) {
throw new ElasticsearchException("Error while getting for request: " + request.toString(), e);
}
@ -385,39 +350,29 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate
@Override
public <T> AggregatedPage<T> queryForPage(SearchQuery query, Class<T> clazz) {
return queryForPage(query, clazz, resultsMapper);
}
@Override
public <T> AggregatedPage<T> queryForPage(SearchQuery query, Class<T> clazz, SearchResultMapper mapper) {
SearchResponse response = doSearch(prepareSearch(query, clazz), query);
return mapper.mapResults(response, clazz, query.getPageable());
return elasticsearchConverter.mapResults(SearchDocumentResponse.from(response), clazz, query.getPageable());
}
@Override
public <T> List<Page<T>> queryForPage(List<SearchQuery> queries, Class<T> clazz) {
return queryForPage(queries, clazz, resultsMapper);
}
private <T> List<Page<T>> doMultiSearch(List<SearchQuery> queries, Class<T> clazz, MultiSearchRequest request,
SearchResultMapper resultsMapper) {
private <T> List<Page<T>> doMultiSearch(List<SearchQuery> queries, Class<T> clazz, MultiSearchRequest request) {
MultiSearchResponse.Item[] items = getMultiSearchResult(request);
List<Page<T>> res = new ArrayList<>(queries.size());
int c = 0;
for (SearchQuery query : queries) {
res.add(resultsMapper.mapResults(items[c++].getResponse(), clazz, query.getPageable()));
res.add(elasticsearchConverter.mapResults(SearchDocumentResponse.from(items[c++].getResponse()), clazz,
query.getPageable()));
}
return res;
}
private List<Page<?>> doMultiSearch(List<SearchQuery> queries, List<Class<?>> classes, MultiSearchRequest request,
SearchResultMapper resultsMapper) {
private List<Page<?>> doMultiSearch(List<SearchQuery> queries, List<Class<?>> classes, MultiSearchRequest request) {
MultiSearchResponse.Item[] items = getMultiSearchResult(request);
List<Page<?>> res = new ArrayList<>(queries.size());
int c = 0;
Iterator<Class<?>> it = classes.iterator();
for (SearchQuery query : queries) {
res.add(resultsMapper.mapResults(items[c++].getResponse(), it.next(), query.getPageable()));
res.add(elasticsearchConverter.mapResults(SearchDocumentResponse.from(items[c++].getResponse()), it.next(),
query.getPageable()));
}
return res;
}
@ -435,27 +390,22 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate
}
@Override
public <T> List<Page<T>> queryForPage(List<SearchQuery> queries, Class<T> clazz, SearchResultMapper mapper) {
public <T> List<Page<T>> queryForPage(List<SearchQuery> queries, Class<T> clazz) {
MultiSearchRequest request = new MultiSearchRequest();
for (SearchQuery query : queries) {
request.add(prepareSearch(prepareSearch(query, clazz), query));
}
return doMultiSearch(queries, clazz, request, mapper);
return doMultiSearch(queries, clazz, request);
}
@Override
public List<Page<?>> queryForPage(List<SearchQuery> queries, List<Class<?>> classes) {
return queryForPage(queries, classes, resultsMapper);
}
@Override
public List<Page<?>> queryForPage(List<SearchQuery> queries, List<Class<?>> classes, SearchResultMapper mapper) {
MultiSearchRequest request = new MultiSearchRequest();
Iterator<Class<?>> it = classes.iterator();
for (SearchQuery query : queries) {
request.add(prepareSearch(prepareSearch(query, it.next()), query));
}
return doMultiSearch(queries, classes, request, mapper);
return doMultiSearch(queries, classes, request);
}
@Override
@ -529,16 +479,11 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate
} catch (IOException e) {
throw new ElasticsearchException("Error for search request: " + request.toString(), e);
}
return resultsMapper.mapResults(response, clazz, criteriaQuery.getPageable());
return elasticsearchConverter.mapResults(SearchDocumentResponse.from(response), clazz, criteriaQuery.getPageable());
}
@Override
public <T> Page<T> queryForPage(StringQuery query, Class<T> clazz) {
return queryForPage(query, clazz, resultsMapper);
}
@Override
public <T> Page<T> queryForPage(StringQuery query, Class<T> clazz, SearchResultMapper mapper) {
SearchRequest request = prepareSearch(query, clazz);
request.source().query((wrapperQuery(query.getSource())));
SearchResponse response;
@ -547,29 +492,23 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate
} catch (IOException e) {
throw new ElasticsearchException("Error for search request: " + request.toString(), e);
}
return mapper.mapResults(response, clazz, query.getPageable());
return elasticsearchConverter.mapResults(SearchDocumentResponse.from(response), clazz, query.getPageable());
}
@Override
public <T> CloseableIterator<T> stream(CriteriaQuery query, Class<T> clazz) {
long scrollTimeInMillis = TimeValue.timeValueMinutes(1).millis();
return doStream(scrollTimeInMillis, startScroll(scrollTimeInMillis, query, clazz), clazz, resultsMapper);
return doStream(scrollTimeInMillis, startScroll(scrollTimeInMillis, query, clazz), clazz);
}
@Override
public <T> CloseableIterator<T> stream(SearchQuery query, Class<T> clazz) {
return stream(query, clazz, resultsMapper);
}
@Override
public <T> CloseableIterator<T> stream(SearchQuery query, Class<T> clazz, SearchResultMapper mapper) {
long scrollTimeInMillis = TimeValue.timeValueMinutes(1).millis();
return doStream(scrollTimeInMillis, startScroll(scrollTimeInMillis, query, clazz, mapper), clazz, mapper);
return doStream(scrollTimeInMillis, startScroll(scrollTimeInMillis, query, clazz), clazz);
}
private <T> CloseableIterator<T> doStream(long scrollTimeInMillis, ScrolledPage<T> page, Class<T> clazz,
SearchResultMapper mapper) {
return StreamQueries.streamResults(page, scrollId -> continueScroll(scrollId, scrollTimeInMillis, clazz, mapper),
private <T> CloseableIterator<T> doStream(long scrollTimeInMillis, ScrolledPage<T> page, Class<T> clazz) {
return StreamQueries.streamResults(page, scrollId -> continueScroll(scrollId, scrollTimeInMillis, clazz),
this::clearScroll);
}
@ -661,7 +600,7 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate
@Override
public <T> List<T> multiGet(SearchQuery searchQuery, Class<T> clazz) {
return resultsMapper.mapResults(getMultiResponse(searchQuery, clazz), clazz);
return elasticsearchConverter.mapDocuments(DocumentAdapters.from(getMultiResponse(searchQuery, clazz)), clazz);
}
private <T> MultiGetResponse getMultiResponse(Query searchQuery, Class<T> clazz) {
@ -698,11 +637,6 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate
}
}
@Override
public <T> List<T> multiGet(SearchQuery searchQuery, Class<T> clazz, MultiGetResultMapper getResultMapper) {
return getResultMapper.mapResults(getMultiResponse(searchQuery, clazz), clazz);
}
@Override
public String index(IndexQuery query) {
String documentId;
@ -1061,27 +995,13 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate
@Override
public <T> ScrolledPage<T> startScroll(long scrollTimeInMillis, SearchQuery searchQuery, Class<T> clazz) {
SearchResponse response = doScroll(prepareScroll(searchQuery, scrollTimeInMillis, clazz), searchQuery);
return resultsMapper.mapResults(response, clazz, null);
return elasticsearchConverter.mapResults(SearchDocumentResponse.from(response), clazz, null);
}
@Override
public <T> ScrolledPage<T> startScroll(long scrollTimeInMillis, CriteriaQuery criteriaQuery, Class<T> clazz) {
SearchResponse response = doScroll(prepareScroll(criteriaQuery, scrollTimeInMillis, clazz), criteriaQuery);
return resultsMapper.mapResults(response, clazz, null);
}
@Override
public <T> ScrolledPage<T> startScroll(long scrollTimeInMillis, SearchQuery searchQuery, Class<T> clazz,
SearchResultMapper mapper) {
SearchResponse response = doScroll(prepareScroll(searchQuery, scrollTimeInMillis, clazz), searchQuery);
return mapper.mapResults(response, clazz, null);
}
@Override
public <T> ScrolledPage<T> startScroll(long scrollTimeInMillis, CriteriaQuery criteriaQuery, Class<T> clazz,
SearchResultMapper mapper) {
SearchResponse response = doScroll(prepareScroll(criteriaQuery, scrollTimeInMillis, clazz), criteriaQuery);
return mapper.mapResults(response, clazz, null);
return elasticsearchConverter.mapResults(SearchDocumentResponse.from(response), clazz, null);
}
@Override
@ -1094,21 +1014,7 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate
} catch (IOException e) {
throw new ElasticsearchException("Error for search request with scroll: " + request.toString(), e);
}
return resultsMapper.mapResults(response, clazz, Pageable.unpaged());
}
@Override
public <T> ScrolledPage<T> continueScroll(@Nullable String scrollId, long scrollTimeInMillis, Class<T> clazz,
SearchResultMapper mapper) {
SearchScrollRequest request = new SearchScrollRequest(scrollId);
request.scroll(TimeValue.timeValueMillis(scrollTimeInMillis));
SearchResponse response;
try {
response = client.searchScroll(request, RequestOptions.DEFAULT);
} catch (IOException e) {
throw new ElasticsearchException("Error for search request with scroll: " + request.toString(), e);
}
return mapper.mapResults(response, clazz, Pageable.unpaged());
return elasticsearchConverter.mapResults(SearchDocumentResponse.from(response), clazz, Pageable.unpaged());
}
@Override
@ -1426,7 +1332,6 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate
}
private IndexRequest prepareIndex(IndexQuery query) {
try {
String indexName = StringUtils.isEmpty(query.getIndexName())
? retrieveIndexNameFromPersistentEntity(query.getObject().getClass())[0]
: query.getIndexName();
@ -1444,8 +1349,7 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate
} else {
indexRequest = new IndexRequest(indexName, type);
}
indexRequest.source(resultsMapper.getEntityMapper().mapToString(query.getObject()),
Requests.INDEX_CONTENT_TYPE);
indexRequest.source(elasticsearchConverter.mapObject(query.getObject()).toJson(), Requests.INDEX_CONTENT_TYPE);
} else if (query.getSource() != null) {
indexRequest = new IndexRequest(indexName, type, query.getId()).source(query.getSource(),
Requests.INDEX_CONTENT_TYPE);
@ -1460,9 +1364,6 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate
}
return indexRequest;
} catch (IOException e) {
throw new ElasticsearchException("failed to index the document [id: " + query.getId() + "]", e);
}
}
@Override
@ -1626,10 +1527,6 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate
return values;
}
protected ResultsMapper getResultsMapper() {
return resultsMapper;
}
@Deprecated
public static String readFileFromClasspath(String url) {
return ResourceUtil.readFileFromClasspath(url);
@ -1651,4 +1548,5 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate
public SearchResponse suggest(SuggestBuilder suggestion, Class clazz) {
return suggest(suggestion, retrieveIndexNameFromPersistentEntity(clazz));
}
}

View File

@ -19,7 +19,6 @@ import static org.elasticsearch.client.Requests.*;
import static org.elasticsearch.index.query.QueryBuilders.*;
import static org.springframework.util.CollectionUtils.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@ -86,11 +85,11 @@ import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Setting;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
import org.springframework.data.elasticsearch.core.document.DocumentAdapters;
import org.springframework.data.elasticsearch.core.document.SearchDocumentResponse;
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.data.elasticsearch.support.SearchHitsUtil;
import org.springframework.data.util.CloseableIterator;
@ -128,54 +127,29 @@ import org.springframework.util.StringUtils;
*/
@Deprecated
public class ElasticsearchTemplate extends AbstractElasticsearchTemplate
implements ElasticsearchOperations, EsClient<Client>, ApplicationContextAware {
implements EsClient<Client>, ApplicationContextAware {
private static final Logger QUERY_LOGGER = LoggerFactory
.getLogger("org.springframework.data.elasticsearch.core.QUERY");
private static final Logger LOGGER = LoggerFactory.getLogger(ElasticsearchTemplate.class);
private Client client;
private ResultsMapper resultsMapper;
private String searchTimeout;
public ElasticsearchTemplate(Client client) {
MappingElasticsearchConverter mappingElasticsearchConverter = createElasticsearchConverter();
initialize(client, mappingElasticsearchConverter,
new DefaultResultMapper(mappingElasticsearchConverter.getMappingContext()));
}
public ElasticsearchTemplate(Client client, ElasticsearchConverter elasticsearchConverter,
EntityMapper entityMapper) {
initialize(client, elasticsearchConverter,
new DefaultResultMapper(elasticsearchConverter.getMappingContext(), entityMapper));
}
public ElasticsearchTemplate(Client client, ResultsMapper resultsMapper) {
initialize(client, createElasticsearchConverter(), resultsMapper);
initialize(client, createElasticsearchConverter());
}
public ElasticsearchTemplate(Client client, ElasticsearchConverter elasticsearchConverter) {
this(client, elasticsearchConverter, new DefaultResultMapper(elasticsearchConverter.getMappingContext()));
initialize(client, elasticsearchConverter);
}
private MappingElasticsearchConverter createElasticsearchConverter() {
return new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext());
}
public ElasticsearchTemplate(Client client, ElasticsearchConverter elasticsearchConverter,
ResultsMapper resultsMapper) {
initialize(client, elasticsearchConverter, resultsMapper);
}
private void initialize(Client client, ElasticsearchConverter elasticsearchConverter, ResultsMapper resultsMapper) {
private void initialize(Client client, ElasticsearchConverter elasticsearchConverter) {
Assert.notNull(client, "Client must not be null!");
Assert.notNull(elasticsearchConverter, "elasticsearchConverter must not be null.");
Assert.notNull(resultsMapper, "ResultsMapper must not be null!");
this.client = client;
this.elasticsearchConverter = elasticsearchConverter;
this.resultsMapper = resultsMapper;
}
@Override
@ -278,24 +252,14 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate
return getMapping(getPersistentEntityFor(clazz).getIndexName(), getPersistentEntityFor(clazz).getIndexType());
}
@Override
public ElasticsearchConverter getElasticsearchConverter() {
return elasticsearchConverter;
}
@Override
public <T> T queryForObject(GetQuery query, Class<T> clazz) {
return queryForObject(query, clazz, resultsMapper);
}
@Override
public <T> T queryForObject(GetQuery query, Class<T> clazz, GetResultMapper mapper) {
ElasticsearchPersistentEntity<T> persistentEntity = getPersistentEntityFor(clazz);
GetResponse response = client
.prepareGet(persistentEntity.getIndexName(), persistentEntity.getIndexType(), query.getId()).execute()
.actionGet();
T entity = mapper.mapResult(response, clazz);
T entity = elasticsearchConverter.mapDocument(DocumentAdapters.from(response), clazz);
return entity;
}
@ -318,48 +282,38 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate
@Override
public <T> AggregatedPage<T> queryForPage(SearchQuery query, Class<T> clazz) {
return queryForPage(query, clazz, resultsMapper);
}
@Override
public <T> AggregatedPage<T> queryForPage(SearchQuery query, Class<T> clazz, SearchResultMapper mapper) {
SearchResponse response = doSearch(prepareSearch(query, clazz), query);
return mapper.mapResults(response, clazz, query.getPageable());
return elasticsearchConverter.mapResults(SearchDocumentResponse.from(response), clazz, query.getPageable());
}
@Override
public <T> List<Page<T>> queryForPage(List<SearchQuery> queries, Class<T> clazz) {
return queryForPage(queries, clazz, resultsMapper);
}
@Override
public <T> List<Page<T>> queryForPage(List<SearchQuery> queries, Class<T> clazz, SearchResultMapper mapper) {
MultiSearchRequest request = new MultiSearchRequest();
for (SearchQuery query : queries) {
request.add(prepareSearch(prepareSearch(query, clazz), query));
}
return doMultiSearch(queries, clazz, request, mapper);
return doMultiSearch(queries, clazz, request);
}
private <T> List<Page<T>> doMultiSearch(List<SearchQuery> queries, Class<T> clazz, MultiSearchRequest request,
SearchResultMapper resultsMapper) {
private <T> List<Page<T>> doMultiSearch(List<SearchQuery> queries, Class<T> clazz, MultiSearchRequest request) {
MultiSearchResponse.Item[] items = getMultiSearchResult(request);
List<Page<T>> res = new ArrayList<>(queries.size());
int c = 0;
for (SearchQuery query : queries) {
res.add(resultsMapper.mapResults(items[c++].getResponse(), clazz, query.getPageable()));
res.add(elasticsearchConverter.mapResults(SearchDocumentResponse.from(items[c++].getResponse()), clazz,
query.getPageable()));
}
return res;
}
private List<Page<?>> doMultiSearch(List<SearchQuery> queries, List<Class<?>> classes, MultiSearchRequest request,
SearchResultMapper resultsMapper) {
private List<Page<?>> doMultiSearch(List<SearchQuery> queries, List<Class<?>> classes, MultiSearchRequest request) {
MultiSearchResponse.Item[] items = getMultiSearchResult(request);
List<Page<?>> res = new ArrayList<>(queries.size());
int c = 0;
Iterator<Class<?>> it = classes.iterator();
for (SearchQuery query : queries) {
res.add(resultsMapper.mapResults(items[c++].getResponse(), it.next(), query.getPageable()));
res.add(elasticsearchConverter.mapResults(SearchDocumentResponse.from(items[c++].getResponse()), it.next(),
query.getPageable()));
}
return res;
}
@ -374,18 +328,13 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate
@Override
public List<Page<?>> queryForPage(List<SearchQuery> queries, List<Class<?>> classes) {
return queryForPage(queries, classes, resultsMapper);
}
@Override
public List<Page<?>> queryForPage(List<SearchQuery> queries, List<Class<?>> classes, SearchResultMapper mapper) {
Assert.isTrue(queries.size() == classes.size(), "Queries should have same length with classes");
MultiSearchRequest request = new MultiSearchRequest();
Iterator<Class<?>> it = classes.iterator();
for (SearchQuery query : queries) {
request.add(prepareSearch(prepareSearch(query, it.next()), query));
}
return doMultiSearch(queries, classes, request, mapper);
return doMultiSearch(queries, classes, request);
}
@Override
@ -445,40 +394,29 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate
searchRequestBuilder.setPostFilter(elasticsearchFilter);
SearchResponse response = getSearchResponse(searchRequestBuilder);
return resultsMapper.mapResults(response, clazz, criteriaQuery.getPageable());
return elasticsearchConverter.mapResults(SearchDocumentResponse.from(response), clazz, criteriaQuery.getPageable());
}
@Override
public <T> Page<T> queryForPage(StringQuery query, Class<T> clazz) {
return queryForPage(query, clazz, resultsMapper);
}
@Override
public <T> Page<T> queryForPage(StringQuery query, Class<T> clazz, SearchResultMapper mapper) {
SearchResponse response = getSearchResponse(prepareSearch(query, clazz).setQuery(wrapperQuery(query.getSource())));
return mapper.mapResults(response, clazz, query.getPageable());
return elasticsearchConverter.mapResults(SearchDocumentResponse.from(response), clazz, query.getPageable());
}
@Override
public <T> CloseableIterator<T> stream(CriteriaQuery query, Class<T> clazz) {
long scrollTimeInMillis = TimeValue.timeValueMinutes(1).millis();
return doStream(scrollTimeInMillis, startScroll(scrollTimeInMillis, query, clazz), clazz, resultsMapper);
return doStream(scrollTimeInMillis, startScroll(scrollTimeInMillis, query, clazz), clazz);
}
@Override
public <T> CloseableIterator<T> stream(SearchQuery query, Class<T> clazz) {
return stream(query, clazz, resultsMapper);
}
@Override
public <T> CloseableIterator<T> stream(SearchQuery query, Class<T> clazz, SearchResultMapper mapper) {
long scrollTimeInMillis = TimeValue.timeValueMinutes(1).millis();
return doStream(scrollTimeInMillis, startScroll(scrollTimeInMillis, query, clazz, mapper), clazz, mapper);
return doStream(scrollTimeInMillis, startScroll(scrollTimeInMillis, query, clazz), clazz);
}
private <T> CloseableIterator<T> doStream(long scrollTimeInMillis, ScrolledPage<T> page, Class<T> clazz,
SearchResultMapper mapper) {
return StreamQueries.streamResults(page, scrollId -> continueScroll(scrollId, scrollTimeInMillis, clazz, mapper),
private <T> CloseableIterator<T> doStream(long scrollTimeInMillis, ScrolledPage<T> page, Class<T> clazz) {
return StreamQueries.streamResults(page, scrollId -> continueScroll(scrollId, scrollTimeInMillis, clazz),
this::clearScroll);
}
@ -560,7 +498,7 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate
@Override
public <T> List<T> multiGet(SearchQuery searchQuery, Class<T> clazz) {
return resultsMapper.mapResults(getMultiResponse(searchQuery, clazz), clazz);
return elasticsearchConverter.mapDocuments(DocumentAdapters.from(getMultiResponse(searchQuery, clazz)), clazz);
}
private <T> MultiGetResponse getMultiResponse(Query searchQuery, Class<T> clazz) {
@ -593,11 +531,6 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate
return builder.execute().actionGet();
}
@Override
public <T> List<T> multiGet(SearchQuery searchQuery, Class<T> clazz, MultiGetResultMapper getResultMapper) {
return getResultMapper.mapResults(getMultiResponse(searchQuery, clazz), clazz);
}
@Override
public String index(IndexQuery query) {
String documentId = prepareIndex(query).execute().actionGet().getId();
@ -890,39 +823,23 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate
return getSearchResponse(requestBuilder.setQuery(searchQuery.getQuery()));
}
@Override
public <T> ScrolledPage<T> startScroll(long scrollTimeInMillis, SearchQuery searchQuery, Class<T> clazz) {
SearchResponse response = doScroll(prepareScroll(searchQuery, scrollTimeInMillis, clazz), searchQuery);
return resultsMapper.mapResults(response, clazz, null);
return elasticsearchConverter.mapResults(SearchDocumentResponse.from(response), clazz, null);
}
@Override
public <T> ScrolledPage<T> startScroll(long scrollTimeInMillis, CriteriaQuery criteriaQuery, Class<T> clazz) {
SearchResponse response = doScroll(prepareScroll(criteriaQuery, scrollTimeInMillis, clazz), criteriaQuery);
return resultsMapper.mapResults(response, clazz, null);
}
public <T> ScrolledPage<T> startScroll(long scrollTimeInMillis, SearchQuery searchQuery, Class<T> clazz,
SearchResultMapper mapper) {
SearchResponse response = doScroll(prepareScroll(searchQuery, scrollTimeInMillis, clazz), searchQuery);
return mapper.mapResults(response, clazz, null);
}
public <T> ScrolledPage<T> startScroll(long scrollTimeInMillis, CriteriaQuery criteriaQuery, Class<T> clazz,
SearchResultMapper mapper) {
SearchResponse response = doScroll(prepareScroll(criteriaQuery, scrollTimeInMillis, clazz), criteriaQuery);
return mapper.mapResults(response, clazz, null);
return elasticsearchConverter.mapResults(SearchDocumentResponse.from(response), clazz, null);
}
@Override
public <T> ScrolledPage<T> continueScroll(@Nullable String scrollId, long scrollTimeInMillis, Class<T> clazz) {
SearchResponse response = getSearchResponse(
client.prepareSearchScroll(scrollId).setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)).execute());
return resultsMapper.mapResults(response, clazz, Pageable.unpaged());
}
public <T> ScrolledPage<T> continueScroll(@Nullable String scrollId, long scrollTimeInMillis, Class<T> clazz,
SearchResultMapper mapper) {
SearchResponse response = getSearchResponse(
client.prepareSearchScroll(scrollId).setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)).execute());
return mapper.mapResults(response, clazz, Pageable.unpaged());
return elasticsearchConverter.mapResults(SearchDocumentResponse.from(response), clazz, Pageable.unpaged());
}
@Override
@ -1189,7 +1106,6 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate
}
private IndexRequestBuilder prepareIndex(IndexQuery query) {
try {
String indexName = StringUtils.isEmpty(query.getIndexName())
? retrieveIndexNameFromPersistentEntity(query.getObject().getClass())[0]
: query.getIndexName();
@ -1207,7 +1123,7 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate
} else {
indexRequestBuilder = client.prepareIndex(indexName, type);
}
indexRequestBuilder.setSource(resultsMapper.getEntityMapper().mapToString(query.getObject()),
indexRequestBuilder.setSource(elasticsearchConverter.mapObject(query.getObject()).toJson(),
Requests.INDEX_CONTENT_TYPE);
} else if (query.getSource() != null) {
indexRequestBuilder = client.prepareIndex(indexName, type, query.getId()).setSource(query.getSource(),
@ -1223,9 +1139,6 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate
}
return indexRequestBuilder;
} catch (IOException e) {
throw new ElasticsearchException("failed to index the document [id: " + query.getId() + "]", e);
}
}
@Override
@ -1337,10 +1250,6 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate
return values;
}
protected ResultsMapper getResultsMapper() {
return resultsMapper;
}
@Deprecated
public static String readFileFromClasspath(String url) {
return ResourceUtil.readFileFromClasspath(url);
@ -1353,4 +1262,5 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate
public SearchResponse suggest(SuggestBuilder suggestion, Class clazz) {
return suggest(suggestion, retrieveIndexNameFromPersistentEntity(clazz));
}
}

View File

@ -1,61 +0,0 @@
/*
* Copyright 2014-2019 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.core;
import java.io.IOException;
import java.util.Map;
import org.springframework.data.elasticsearch.Document;
import org.springframework.lang.Nullable;
/**
* DocumentMapper interface, it will allow to customize how we mapping object to json
*
* @author Artur Konczak
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Christoph Strobl
* @author Mark Paluch
*/
public interface EntityMapper {
default String mapToString(Object object) throws IOException {
return mapObject(object).toJson();
}
<T> T mapToObject(String source, Class<T> clazz) throws IOException;
/**
* Map the given {@literal source} to {@link Document}.
*
* @param source must not be {@literal null}.
* @return never {@literal null}
* @since 3.2
*/
Document mapObject(Object source);
/**
* Map the given {@link Document} into an instance of the {@literal targetType}.
*
* @param source must not be {@literal null}.
* @param targetType must not be {@literal null}.
* @param <T>
* @return can be {@literal null}.
* @since 3.2
*/
@Nullable
<T> T readObject(Document source, Class<T> targetType);
}

View File

@ -1,42 +0,0 @@
/*
* Copyright 2014-2019 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.core;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.index.get.GetResult;
import org.springframework.lang.Nullable;
/**
* @author Artur Konczak
* @author Mohsin Husen
* @author Christoph Strobl
*/
public interface GetResultMapper {
<T> T mapResult(GetResponse response, Class<T> clazz);
/**
* Map a single {@link GetResult} to the given {@link Class type}.
*
* @param getResult must not be {@literal null}.
* @param type must not be {@literal null}.
* @param <T>
* @return can be {@literal null}.
* @since 3.2
*/
@Nullable
<T> T mapGetResult(GetResult getResult, Class<T> type);
}

View File

@ -1,29 +0,0 @@
/*
* Copyright 2014-2019 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.core;
import java.util.List;
import org.elasticsearch.action.get.MultiGetResponse;
/**
* @author Mohsin Husen
*/
public interface MultiGetResultMapper {
<T> List<T> mapResults(MultiGetResponse responses, Class<T> clazz);
}

View File

@ -21,7 +21,6 @@ import lombok.NonNull;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -59,6 +58,7 @@ import org.springframework.data.elasticsearch.core.EntityOperations.Entity;
import org.springframework.data.elasticsearch.core.EntityOperations.IndexCoordinates;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
import org.springframework.data.elasticsearch.core.document.DocumentAdapters;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
@ -89,7 +89,6 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera
private final ReactiveElasticsearchClient client;
private final ElasticsearchConverter converter;
private final @NonNull MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext;
private final ResultsMapper resultMapper;
private final ElasticsearchExceptionTranslator exceptionTranslator;
private final EntityOperations operations;
@ -101,17 +100,11 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera
}
public ReactiveElasticsearchTemplate(ReactiveElasticsearchClient client, ElasticsearchConverter converter) {
this(client, converter, new DefaultResultMapper(converter.getMappingContext()));
}
public ReactiveElasticsearchTemplate(ReactiveElasticsearchClient client, ElasticsearchConverter converter,
ResultsMapper resultsMapper) {
this.client = client;
this.converter = converter;
this.mappingContext = converter.getMappingContext();
this.resultMapper = resultsMapper;
this.exceptionTranslator = new ElasticsearchExceptionTranslator();
this.operations = new EntityOperations(this.mappingContext);
}
@ -155,11 +148,7 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera
? new IndexRequest(indexCoordinates.getIndexName(), indexCoordinates.getTypeName(), converter.convertId(id))
: new IndexRequest(indexCoordinates.getIndexName(), indexCoordinates.getTypeName());
try {
request.source(resultMapper.getEntityMapper().mapToString(value), Requests.INDEX_CONTENT_TYPE);
} catch (IOException e) {
throw new RuntimeException(e);
}
request.source(converter.mapObject(value).toJson(), Requests.INDEX_CONTENT_TYPE);
if (entity.isVersionedEntity()) {
@ -185,7 +174,7 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera
Assert.notNull(id, "Id must not be null!");
return doFindById(id, getPersistentEntity(entityType), index, type)
.map(it -> resultMapper.mapGetResult(it, entityType));
.map(it -> converter.mapDocument(DocumentAdapters.from(it), entityType));
}
private Mono<GetResult> doFindById(String id, ElasticsearchPersistentEntity<?> entity, @Nullable String index,
@ -232,7 +221,7 @@ public class ReactiveElasticsearchTemplate implements ReactiveElasticsearchOpera
Class<T> resultType) {
return doFind(query, getPersistentEntity(entityType), index, type)
.map(it -> resultMapper.mapSearchHit(it, resultType));
.map(it -> converter.mapDocument(DocumentAdapters.from(it), resultType));
}
private Flux<SearchHit> doFind(Query query, ElasticsearchPersistentEntity<?> entity, @Nullable String index,

View File

@ -1,120 +0,0 @@
/*
* Copyright 2013-2019 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.core;
import java.io.IOException;
import org.elasticsearch.index.get.GetResult;
import org.elasticsearch.search.SearchHit;
import org.springframework.data.elasticsearch.Document;
import org.springframework.data.elasticsearch.ElasticsearchException;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
* ResultsMapper
*
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Artur Konczak
* @author Christoph Strobl
* @author Mark Paluch
*/
public interface ResultsMapper extends SearchResultMapper, GetResultMapper, MultiGetResultMapper {
EntityMapper getEntityMapper();
/**
* Get the configured {@link ProjectionFactory}. <br />
* <strong>NOTE</strong> Should be overwritten in implementation to make use of the type cache.
*
* @since 3.2
*/
default ProjectionFactory getProjectionFactory() {
return new SpelAwareProxyProjectionFactory();
}
@Nullable
@Deprecated
default <T> T mapEntity(String source, Class<T> clazz) {
if (StringUtils.isEmpty(source)) {
return null;
}
try {
return getEntityMapper().mapToObject(source, clazz);
} catch (IOException e) {
throw new ElasticsearchException("failed to map source [ " + source + "] to class " + clazz.getSimpleName(), e);
}
}
/**
* Map a single {@link Document} to an instance of the given type.
*
* @param document must not be {@literal null}.
* @param type must not be {@literal null}.
* @param <T>
* @return can be {@literal null} if the {@link Document#isEmpty() is empty}.
* @since 4.0
*/
@Nullable
default <T> T mapDocument(Document document, Class<T> type) {
Object mappedResult = getEntityMapper().readObject(document, type);
if (mappedResult == null) {
return (T) null;
}
if (type.isInterface() || !ClassUtils.isAssignableValue(type, mappedResult)) {
return getProjectionFactory().createProjection(type, mappedResult);
}
return type.cast(mappedResult);
}
/**
* Map a single {@link GetResult} to an instance of the given type.
*
* @param getResult must not be {@literal null}.
* @param type must not be {@literal null}.
* @param <T>
* @return can be {@literal null} if the {@link GetResult#isSourceEmpty() is empty}.
* @since 3.2
*/
@Nullable
default <T> T mapGetResult(GetResult getResult, Class<T> type) {
return mapDocument(DocumentAdapters.from(getResult), type);
}
/**
* Map a single {@link SearchHit} to an instance of the given type.
*
* @param searchHit must not be {@literal null}.
* @param type must not be {@literal null}.
* @param <T>
* @return can be {@literal null} if the {@link SearchHit} does not have {@link SearchHit#hasSource() a source}.
* @since 3.2
*/
@Nullable
default <T> T mapSearchHit(SearchHit searchHit, Class<T> type) {
return mapDocument(DocumentAdapters.from(searchHit), type);
}
}

View File

@ -1,44 +0,0 @@
/*
* Copyright 2014-2019 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.core;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.SearchHit;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.lang.Nullable;
/**
* @author Artur Konczak
* @author Petar Tahchiev
* @author Christoph Strobl
*/
public interface SearchResultMapper {
<T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable);
/**
* Map a single {@link SearchHit} to the given {@link Class type}.
*
* @param searchHit must not be {@literal null}.
* @param type must not be {@literal null}.
* @param <T>
* @return can be {@literal null}.
* @since 3.2
*/
@Nullable
<T> T mapSearchHit(SearchHit searchHit, Class<T> type);
}

View File

@ -1,49 +0,0 @@
/*
* Copyright 2019 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.core;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.SearchHit;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
/**
* Adapter utility for {@link SearchResultMapper} that wish to implement a subset of mapping methods. Default
* implementations throw {@link UnsupportedOperationException}.
*
* @author Mark Paluch
* @since 3.2
*/
abstract class SearchResultMapperAdapter implements SearchResultMapper {
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.core.SearchResultMapper#mapResults(org.elasticsearch.action.search.SearchResponse, java.lang.Class, org.springframework.data.domain.Pageable)
*/
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
throw new UnsupportedOperationException();
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.core.SearchResultMapper#mapSearchHit(org.elasticsearch.search.SearchHit, java.lang.Class)
*/
@Override
public <T> T mapSearchHit(SearchHit searchHit, Class<T> type) {
throw new UnsupportedOperationException();
}
}

View File

@ -22,12 +22,14 @@ import org.elasticsearch.search.aggregations.Aggregations;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.FacetedPageImpl;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.document.SearchDocumentResponse;
/**
* @author Petar Tahchiev
* @author Artur Konczak
* @author Mohsin Husen
* @author Sascha Woo
* @author Peter-Josef Meisch
*/
public class AggregatedPageImpl<T> extends FacetedPageImpl<T> implements AggregatedPage<T> {
@ -95,6 +97,11 @@ public class AggregatedPageImpl<T> extends FacetedPageImpl<T> implements Aggrega
this.maxScore = maxScore;
}
public AggregatedPageImpl(List<T> content, Pageable pageable, SearchDocumentResponse response) {
this(content, pageable, response.getTotalHits(), response.getAggregations(), response.getScrollId(),
response.getMaxScore());
}
@Override
public boolean hasAggregations() {
return aggregations != null;

View File

@ -15,10 +15,18 @@
*/
package org.springframework.data.elasticsearch.core.convert;
import java.util.List;
import org.springframework.data.convert.EntityConverter;
import org.springframework.data.elasticsearch.Document;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.document.SearchDocumentResponse;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@ -48,4 +56,47 @@ public interface ElasticsearchConverter
return getConversionService().convert(idValue, String.class);
}
<T> AggregatedPage<T> mapResults(SearchDocumentResponse response, Class<T> clazz, Pageable pageable);
/**
* Get the configured {@link ProjectionFactory}. <br />
* <strong>NOTE</strong> Should be overwritten in implementation to make use of the type cache.
*
* @since 3.2
*/
default ProjectionFactory getProjectionFactory() {
return new SpelAwareProxyProjectionFactory();
}
/**
* Map a single {@link Document} to an instance of the given type.
*
* @param document must not be {@literal null}.
* @param type must not be {@literal null}.
* @param <T>
* @return can be {@literal null} if the {@link Document#isEmpty()} is true.
* @since 4.0
*/
@Nullable
<T> T mapDocument(Document document, Class<T> type);
/**
* Map a list of {@link Document}s to alist of instance of the given type.
*
* @param documents must not be {@literal null}.
* @param type must not be {@literal null}.
* @param <T>
* @return a list obtained by calling {@link #mapDocument(Document, Class)} on the elements of the list.
* @since 4.0
*/
<T> List<T> mapDocuments(List<Document> documents, Class<T> type);
/**
* Map an object to a {@link Document}.
*
* @param source
* @return will not be {@literal null}.
*/
Document mapObject(Object source);
}

View File

@ -17,9 +17,18 @@ package org.springframework.data.elasticsearch.core.convert;
import lombok.RequiredArgsConstructor;
import java.io.IOException;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
@ -32,9 +41,14 @@ import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.convert.CustomConversions;
import org.springframework.data.convert.EntityInstantiator;
import org.springframework.data.convert.EntityInstantiators;
import org.springframework.data.elasticsearch.Document;
import org.springframework.data.elasticsearch.SearchDocument;
import org.springframework.data.elasticsearch.core.EntityMapper;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.ElasticsearchException;
import org.springframework.data.elasticsearch.annotations.ScriptedField;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.document.SearchDocument;
import org.springframework.data.elasticsearch.core.document.SearchDocumentResponse;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.mapping.PersistentPropertyAccessor;
@ -51,9 +65,6 @@ import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
/**
* Elasticsearch specific {@link org.springframework.data.convert.EntityConverter} implementation based on domain type
* {@link ElasticsearchPersistentEntity metadata}.
@ -66,11 +77,10 @@ import com.fasterxml.jackson.databind.ObjectReader;
* @since 3.2
*/
public class MappingElasticsearchConverter
implements ElasticsearchConverter, EntityMapper, ApplicationContextAware, InitializingBean {
implements ElasticsearchConverter, ApplicationContextAware, InitializingBean {
private final MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext;
private final GenericConversionService conversionService;
private final ObjectReader objectReader;
private CustomConversions conversions = new ElasticsearchCustomConversions(Collections.emptyList());
private EntityInstantiators instantiators = new EntityInstantiators();
@ -91,9 +101,6 @@ public class MappingElasticsearchConverter
this.mappingContext = mappingContext;
this.conversionService = conversionService != null ? conversionService : new DefaultConversionService();
this.typeMapper = ElasticsearchTypeMapper.create(mappingContext);
ObjectMapper objectMapper = new ObjectMapper();
objectReader = objectMapper.readerFor(HashMap.class);
}
@Override
@ -103,8 +110,6 @@ public class MappingElasticsearchConverter
}
}
// --> GETTERS / SETTERS
@Override
public MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> getMappingContext() {
return mappingContext;
@ -145,8 +150,6 @@ public class MappingElasticsearchConverter
conversions.registerConvertersIn(conversionService);
}
// --> READ
@SuppressWarnings("unchecked")
@Override
@Nullable
@ -156,7 +159,7 @@ public class MappingElasticsearchConverter
@SuppressWarnings("unchecked")
@Nullable
protected <R> R doRead(Map<String, Object> source, TypeInformation<R> typeHint) {
protected <R> R doRead(Document source, TypeInformation<R> typeHint) {
if (source == null) {
return null;
@ -189,8 +192,48 @@ public class MappingElasticsearchConverter
R instance = (R) instantiator.createInstance(targetEntity,
new PersistentEntityParameterValueProvider<>(targetEntity, propertyValueProvider, null));
return targetEntity.requiresPropertyPopulation() ? readProperties(targetEntity, instance, propertyValueProvider)
: instance;
if (!targetEntity.requiresPropertyPopulation()) {
return instance;
}
R result = readProperties(targetEntity, instance, propertyValueProvider);
if (source instanceof Document) {
Document document = (Document) source;
if (document.hasId()) {
ElasticsearchPersistentProperty idProperty = targetEntity.getIdProperty();
PersistentPropertyAccessor<R> accessor = new ConvertingPropertyAccessor<>(
targetEntity.getPropertyAccessor(result), conversionService);
// Only deal with String because ES generated Ids are strings !
if (idProperty != null && idProperty.getType().isAssignableFrom(String.class)) {
accessor.setProperty(idProperty, document.getId());
}
}
if (document.hasVersion()) {
long version = document.getVersion();
ElasticsearchPersistentProperty versionProperty = targetEntity.getVersionProperty();
// Only deal with Long because ES versions are longs !
if (versionProperty != null && versionProperty.getType().isAssignableFrom(Long.class)) {
// check that a version was actually returned in the response, -1 would indicate that
// a search didn't request the version ids in the response, which would be an issue
Assert.isTrue(version != -1, "Version in response is -1");
targetEntity.getPropertyAccessor(result).setProperty(versionProperty, version);
}
}
}
if (source instanceof SearchDocument) {
SearchDocument searchDocument = (SearchDocument) source;
if (targetEntity.hasScoreProperty()) {
targetEntity.getPropertyAccessor(result) //
.setProperty(targetEntity.getScoreProperty(), searchDocument.getScore());
}
populateScriptFields(result, searchDocument);
}
return result;
}
protected <R> R readProperties(ElasticsearchPersistentEntity<?> entity, R instance,
@ -350,8 +393,6 @@ public class MappingElasticsearchConverter
doWrite(source, sink, type);
}
// --> WRITE
protected void doWrite(@Nullable Object source, Document sink, @Nullable TypeInformation<? extends Object> typeHint) {
if (source == null) {
@ -546,11 +587,24 @@ public class MappingElasticsearchConverter
}
@Override
public <T> T mapToObject(String source, Class<T> clazz) throws IOException {
return read(clazz, Document.from(objectReader.readValue(source)));
@Nullable
public <T> T mapDocument(Document document, Class<T> type) {
Object mappedResult = read(type, document);
if (mappedResult == null) {
return (T) null;
}
// --> LEGACY
return type.isInterface() || !ClassUtils.isAssignableValue(type, mappedResult)
? getProjectionFactory().createProjection(type, mappedResult)
: type.cast(mappedResult);
}
@Override
public <T> List<T> mapDocuments(List<Document> documents, Class<T> type) {
return documents.stream().map(it -> mapDocument(it, type)).collect(Collectors.toList());
}
@Override
public Document mapObject(Object source) {
@ -560,13 +614,6 @@ public class MappingElasticsearchConverter
return target;
}
@Override
public <T> T readObject(Document source, Class<T> targetType) {
return read(targetType, source);
}
// --> PRIVATE HELPERS
private boolean requiresTypeHint(TypeInformation<?> type, Class<?> actualType,
@Nullable TypeInformation<?> container) {
@ -649,7 +696,37 @@ public class MappingElasticsearchConverter
return conversions.isSimpleType(type);
}
// --> OHTER STUFF
@Override
public <T> AggregatedPage<T> mapResults(SearchDocumentResponse response, Class<T> type, Pageable pageable) {
List<T> results = response.getSearchDocuments().stream() //
.map(searchDocument -> mapDocument(searchDocument, type)).collect(Collectors.toList());
return new AggregatedPageImpl<T>(results, pageable, response);
}
private <T> void populateScriptFields(T result, SearchDocument searchDocument) {
Map<String, List<Object>> fields = searchDocument.getFields();
if (!fields.isEmpty()) {
for (java.lang.reflect.Field field : result.getClass().getDeclaredFields()) {
ScriptedField scriptedField = field.getAnnotation(ScriptedField.class);
if (scriptedField != null) {
String name = scriptedField.name().isEmpty() ? field.getName() : scriptedField.name();
Object value = searchDocument.getFieldValue(name);
if (value != null) {
field.setAccessible(true);
try {
field.set(result, value);
} catch (IllegalArgumentException e) {
throw new ElasticsearchException("failed to set scripted field: " + name + " with value: " + value, e);
} catch (IllegalAccessException e) {
throw new ElasticsearchException("failed to access scripted field: " + name, e);
}
}
}
}
}
}
static class MapValueAccessor {

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.elasticsearch;
package org.springframework.data.elasticsearch.core.document;
import java.io.IOException;
import java.util.LinkedHashMap;
@ -24,6 +24,7 @@ import java.util.function.IntSupplier;
import java.util.function.LongSupplier;
import java.util.function.Supplier;
import org.springframework.data.elasticsearch.ElasticsearchException;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

View File

@ -13,13 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.elasticsearch.core;
package org.springframework.data.elasticsearch.core.document;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@ -29,13 +31,12 @@ import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.document.DocumentField;
import org.elasticsearch.index.get.GetResult;
import org.elasticsearch.search.SearchHit;
import org.springframework.data.elasticsearch.Document;
import org.springframework.data.elasticsearch.ElasticsearchException;
import org.springframework.data.elasticsearch.SearchDocument;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@ -45,13 +46,15 @@ import com.fasterxml.jackson.core.JsonGenerator;
/**
* Utility class to adapt {@link org.elasticsearch.action.get.GetResponse},
* {@link org.elasticsearch.index.get.GetResult}, {@link org.elasticsearch.search.SearchHit},
* {@link org.elasticsearch.common.document.DocumentField} to {@link org.springframework.data.elasticsearch.Document}.
* {@link org.elasticsearch.index.get.GetResult}, {@link org.elasticsearch.action.get.MultiGetResponse}
* {@link org.elasticsearch.search.SearchHit}, {@link org.elasticsearch.common.document.DocumentField} to
* {@link Document}.
*
* @author Mark Paluch
* @author Peter-Josef Meisch
* @since 4.0
*/
class DocumentAdapters {
public class DocumentAdapters {
/**
* Create a {@link Document} from {@link GetResponse}.
@ -59,12 +62,17 @@ class DocumentAdapters {
* Returns a {@link Document} using the source if available.
*
* @param source the source {@link GetResponse}.
* @return the adapted {@link Document}.
* @return the adapted {@link Document}, null if source.isExists() returns false.
*/
@Nullable
public static Document from(GetResponse source) {
Assert.notNull(source, "GetResponse must not be null");
if (!source.isExists()) {
return null;
}
if (source.isSourceEmpty()) {
return fromDocumentFields(source, source.getId(), source.getVersion());
}
@ -82,12 +90,17 @@ class DocumentAdapters {
* Returns a {@link Document} using the source if available.
*
* @param source the source {@link GetResult}.
* @return the adapted {@link Document}.
* @return the adapted {@link Document}, null if source.isExists() returns false.
*/
@Nullable
public static Document from(GetResult source) {
Assert.notNull(source, "GetResult must not be null");
if (!source.isExists()) {
return null;
}
if (source.isSourceEmpty()) {
return fromDocumentFields(source, source.getId(), source.getVersion());
}
@ -99,6 +112,21 @@ class DocumentAdapters {
return document;
}
/**
* Creates a List of {@link Document}s from {@link MultiGetResponse}.
*
* @param source the source {@link MultiGetResponse}, not {@literal null}.
* @return a possibly empty list of the Documents.
*/
public static List<Document> from(MultiGetResponse source) {
Assert.notNull(source, "MultiGetResponse must not be null");
return Arrays.stream(source.getResponses()) //
.map(itemResponse -> itemResponse.isFailed() ? null : DocumentAdapters.from(itemResponse.getResponse())) //
.filter(Objects::nonNull).collect(Collectors.toList());
}
/**
* Create a {@link SearchDocument} from {@link SearchHit}.
* <p>
@ -114,7 +142,7 @@ class DocumentAdapters {
BytesReference sourceRef = source.getSourceRef();
if (sourceRef == null || sourceRef.length() == 0) {
return new SearchDocumentAdapter(source.getScore(),
return new SearchDocumentAdapter(source.getScore(), source.getFields(),
fromDocumentFields(source, source.getId(), source.getVersion()));
}
@ -125,7 +153,7 @@ class DocumentAdapters {
document.setVersion(source.getVersion());
}
return new SearchDocumentAdapter(source.getScore(), document);
return new SearchDocumentAdapter(source.getScore(), source.getFields(), document);
}
/**
@ -163,7 +191,7 @@ class DocumentAdapters {
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.Document#hasId()
* @see org.springframework.data.elasticsearch.core.document.Document#hasId()
*/
@Override
public boolean hasId() {
@ -172,7 +200,7 @@ class DocumentAdapters {
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.Document#getId()
* @see org.springframework.data.elasticsearch.core.document.Document#getId()
*/
@Override
public String getId() {
@ -181,7 +209,7 @@ class DocumentAdapters {
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.Document#hasVersion()
* @see org.springframework.data.elasticsearch.core.document.Document#hasVersion()
*/
@Override
public boolean hasVersion() {
@ -190,7 +218,7 @@ class DocumentAdapters {
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.Document#getVersion()
* @see org.springframework.data.elasticsearch.core.document.Document#getVersion()
*/
@Override
public long getVersion() {
@ -351,7 +379,7 @@ class DocumentAdapters {
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.Document#toJson()
* @see org.springframework.data.elasticsearch.core.document.Document#toJson()
*/
@Override
public String toJson() {
@ -410,16 +438,18 @@ class DocumentAdapters {
static class SearchDocumentAdapter implements SearchDocument {
private final float score;
private final Map<String, List<Object>> fields = new HashMap<>();
private final Document delegate;
SearchDocumentAdapter(float score, Document delegate) {
SearchDocumentAdapter(float score, Map<String, DocumentField> fields, Document delegate) {
this.score = score;
this.delegate = delegate;
fields.forEach((name, documentField) -> this.fields.put(name, documentField.getValues()));
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.Document#append(java.lang.String, java.lang.Object)
* @see org.springframework.data.elasticsearch.core.document.Document#append(java.lang.String, java.lang.Object)
*/
@Override
public SearchDocument append(String key, Object value) {
@ -430,7 +460,7 @@ class DocumentAdapters {
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.SearchDocument#getScore()
* @see org.springframework.data.elasticsearch.core.document.SearchDocument#getScore()
*/
@Override
public float getScore() {
@ -439,7 +469,16 @@ class DocumentAdapters {
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.Document#hasId()
* @see org.springframework.data.elasticsearch.core.document.SearchDocument#getFields()
*/
@Override
public Map<String, List<Object>> getFields() {
return fields;
}
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.core.document.Document#hasId()
*/
@Override
public boolean hasId() {
@ -448,7 +487,7 @@ class DocumentAdapters {
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.Document#getId()
* @see org.springframework.data.elasticsearch.core.document.Document#getId()
*/
@Override
public String getId() {
@ -457,7 +496,7 @@ class DocumentAdapters {
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.Document#setId(java.lang.String)
* @see org.springframework.data.elasticsearch.core.document.Document#setId(java.lang.String)
*/
@Override
public void setId(String id) {
@ -466,7 +505,7 @@ class DocumentAdapters {
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.Document#hasVersion()
* @see org.springframework.data.elasticsearch.core.document.Document#hasVersion()
*/
@Override
public boolean hasVersion() {
@ -475,7 +514,7 @@ class DocumentAdapters {
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.Document#getVersion()
* @see org.springframework.data.elasticsearch.core.document.Document#getVersion()
*/
@Override
public long getVersion() {
@ -484,7 +523,7 @@ class DocumentAdapters {
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.Document#setVersion(long)
* @see org.springframework.data.elasticsearch.core.document.Document#setVersion(long)
*/
@Override
public void setVersion(long version) {
@ -493,7 +532,7 @@ class DocumentAdapters {
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.Document#get(java.lang.Object, java.lang.Class)
* @see org.springframework.data.elasticsearch.core.document.Document#get(java.lang.Object, java.lang.Class)
*/
@Override
@Nullable
@ -503,7 +542,7 @@ class DocumentAdapters {
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.Document#toJson()
* @see org.springframework.data.elasticsearch.core.document.Document#toJson()
*/
@Override
public String toJson() {

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.elasticsearch;
package org.springframework.data.elasticsearch.core.document;
import java.util.Collection;
import java.util.LinkedHashMap;
@ -21,6 +21,7 @@ import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import org.springframework.data.elasticsearch.ElasticsearchException;
import org.springframework.lang.Nullable;
import com.fasterxml.jackson.core.JsonProcessingException;
@ -51,7 +52,7 @@ class MapDocument implements Document {
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.Document#hasId()
* @see org.springframework.data.elasticsearch.core.document.Document#hasId()
*/
@Override
public boolean hasId() {
@ -60,7 +61,7 @@ class MapDocument implements Document {
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.Document#getId()
* @see org.springframework.data.elasticsearch.core.document.Document#getId()
*/
@Override
public String getId() {
@ -74,7 +75,7 @@ class MapDocument implements Document {
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.Document#setId(java.lang.String)
* @see org.springframework.data.elasticsearch.core.document.Document#setId(java.lang.String)
*/
@Override
public void setId(String id) {
@ -83,7 +84,7 @@ class MapDocument implements Document {
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.Document#hasVersion()
* @see org.springframework.data.elasticsearch.core.document.Document#hasVersion()
*/
@Override
public boolean hasVersion() {
@ -92,7 +93,7 @@ class MapDocument implements Document {
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.Document#getVersion()
* @see org.springframework.data.elasticsearch.core.document.Document#getVersion()
*/
@Override
public long getVersion() {
@ -106,7 +107,7 @@ class MapDocument implements Document {
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.Document#setVersion(long)
* @see org.springframework.data.elasticsearch.core.document.Document#setVersion(long)
*/
@Override
public void setVersion(long version) {
@ -259,7 +260,7 @@ class MapDocument implements Document {
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.Document#toJson()
* @see org.springframework.data.elasticsearch.core.document.Document#toJson()
*/
@Override
public String toJson() {

View File

@ -13,12 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.elasticsearch;
package org.springframework.data.elasticsearch.core.document;
import java.util.List;
import java.util.Map;
/**
* Extension to {@link Document} exposing a search {@link #getScore() score}.
*
* @author Mark Paluch
* @author Peter-Josef Meisch
* @since 4.0
* @see Document
*/
@ -30,4 +34,22 @@ public interface SearchDocument extends Document {
* @return the search {@code score}.
*/
float getScore();
/**
* @return the fields for the search result, not {@literal null}
*/
Map<String, List<Object>> getFields();
/**
* The first value of the given field.
*
* @param name the field name
*/
default <V> V getFieldValue(final String name) {
List<Object> values = getFields().get(name);
if (values == null || values.isEmpty()) {
return null;
}
return (V) values.get(0);
}
}

View File

@ -0,0 +1,92 @@
/*
* Copyright 2019 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.core.document;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.aggregations.Aggregations;
import org.springframework.data.elasticsearch.support.SearchHitsUtil;
import org.springframework.util.Assert;
/**
* This represents the complete search response from Elasticsearch, including the returned documents. Instances must be
* created with the {@link #from(org.elasticsearch.action.search.SearchResponse)} method.
*
* @author Peter-Josef Meisch
* @since 4.0
*/
public class SearchDocumentResponse {
private long totalHits;
private float maxScore;
private final String scrollId;
private final List<SearchDocument> searchDocuments;
private final Aggregations aggregations;
private SearchDocumentResponse(long totalHits, float maxScore, String scrollId, List<SearchDocument> searchDocuments,
Aggregations aggregations) {
this.totalHits = totalHits;
this.maxScore = maxScore;
this.scrollId = scrollId;
this.searchDocuments = searchDocuments;
this.aggregations = aggregations;
}
public long getTotalHits() {
return totalHits;
}
public float getMaxScore() {
return maxScore;
}
public String getScrollId() {
return scrollId;
}
public List<SearchDocument> getSearchDocuments() {
return searchDocuments;
}
public Aggregations getAggregations() {
return aggregations;
}
/**
* creates a SearchDocumentResponse from the {@link org.elasticsearch.action.search.SearchResponse}
*
* @param searchResponse must not be {@literal null}
* @return
*/
public static SearchDocumentResponse from(SearchResponse searchResponse) {
Assert.notNull(searchResponse, "searchResponse must not be null");
long totalHits = SearchHitsUtil.getTotalCount(searchResponse.getHits());
float maxScore = searchResponse.getHits().getMaxScore();
String scrollId = searchResponse.getScrollId();
List<SearchDocument> searchDocuments = StreamSupport.stream(searchResponse.getHits().spliterator(), false) //
.filter(Objects::nonNull) //
.map(DocumentAdapters::from) //
.collect(Collectors.toList());
Aggregations aggregations = searchResponse.getAggregations();
return new SearchDocumentResponse(totalHits, maxScore, scrollId, searchDocuments, aggregations);
}
}

View File

@ -0,0 +1,5 @@
/**
* interfaces and classes related to the Document representation of Elasticsearch documents.
*/
@org.springframework.lang.NonNullApi
package org.springframework.data.elasticsearch.core.document;

View File

@ -1,4 +1,3 @@
/**
* Infrastructure for the Elasticsearch document-to-object mapping subsystem.
*/

View File

@ -21,6 +21,7 @@ import java.util.Arrays;
import java.util.Collections;
import org.junit.Test;
import org.springframework.data.elasticsearch.core.document.Document;
/**
* Unit tests for {@link Document}.

View File

@ -21,12 +21,12 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.config.ElasticsearchConfigurationSupport;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.springframework.data.elasticsearch.junit.junit4.TestNodeResource;
/**
* configuration class for the classic ElasticsearchTemplate. Needs a {@link TestNodeResource} bean that should be set up in
* the test as ClassRule and exported as bean.
* configuration class for the classic ElasticsearchTemplate. Needs a {@link TestNodeResource} bean that should be set
* up in the test as ClassRule and exported as bean.
*
* @author Peter-Josef Meisch
*/
@ -41,8 +41,9 @@ public class ElasticsearchTestConfiguration extends ElasticsearchConfigurationSu
}
@Bean(name = { "elasticsearchOperations", "elasticsearchTemplate" })
public ElasticsearchTemplate elasticsearchTemplate(Client elasticsearchClient, MappingElasticsearchConverter entityMapper) {
return new ElasticsearchTemplate(elasticsearchClient, entityMapper);
public ElasticsearchTemplate elasticsearchTemplate(Client elasticsearchClient,
ElasticsearchConverter elasticsearchConverter) {
return new ElasticsearchTemplate(elasticsearchClient, elasticsearchConverter);
}
}

View File

@ -18,6 +18,8 @@ package org.springframework.data.elasticsearch.client.reactive;
import static org.assertj.core.api.Assertions.*;
import lombok.SneakyThrows;
import org.junit.ClassRule;
import org.springframework.data.elasticsearch.junit.junit4.TestNodeResource;
import reactor.test.StepVerifier;
import java.io.IOException;
@ -68,9 +70,11 @@ import org.springframework.test.context.junit4.SpringRunner;
* @author Peter-Josef Meisch
*/
@RunWith(SpringRunner.class)
@ContextConfiguration("classpath:infrastructure.xml")
public class ReactiveElasticsearchClientTests {
@ClassRule
public static TestNodeResource testNodeResource = new TestNodeResource();
public @Rule ElasticsearchVersionRule elasticsearchVersion = ElasticsearchVersionRule.any();
static final String INDEX_I = "idx-1-reactive-client-tests";

View File

@ -30,10 +30,8 @@ import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.EntityMapper;
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
/**
@ -102,13 +100,6 @@ public class ElasticsearchConfigurationSupportUnitTests {
assertThat(context.getBean(ReactiveElasticsearchTemplate.class)).isNotNull();
}
@Test // DATAES-530
public void usesConfiguredEntityMapper() {
AbstractApplicationContext context = new AnnotationConfigApplicationContext(EntityMapperConfig.class);
assertThat(context.getBean(EntityMapper.class)).isInstanceOf(MappingElasticsearchConverter.class);
}
@Configuration
static class StubConfig extends ElasticsearchConfigurationSupport {

View File

@ -1,58 +0,0 @@
/*
* Copyright 2013-2019 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.core;
import java.util.List;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
/**
* @author Artur Konczak
* @author Mohsin Husen
*/
public class CustomResultMapper implements ResultsMapper {
private EntityMapper entityMapper;
public CustomResultMapper(EntityMapper entityMapper) {
this.entityMapper = entityMapper;
}
@Override
public EntityMapper getEntityMapper() {
return entityMapper;
}
@Override
public <T> T mapResult(GetResponse response, Class<T> clazz) {
return null; // To change body of implemented methods use File | Settings | File Templates.
}
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
return null; // To change body of implemented methods use File | Settings | File Templates.
}
@Override
public <T> List<T> mapResults(MultiGetResponse responses, Class<T> clazz) {
return null;
}
}

View File

@ -1,336 +0,0 @@
/*
* Copyright 2013-2019 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.core;
import static java.util.Arrays.*;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import static org.springframework.data.elasticsearch.annotations.FieldType.*;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.lang.Double;
import java.lang.Long;
import java.lang.Object;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.get.MultiGetItemResponse;
import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.document.DocumentField;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Version;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.Score;
import org.springframework.data.elasticsearch.annotations.ScriptedField;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
import com.fasterxml.jackson.databind.util.ArrayIterator;
/**
* @author Artur Konczak
* @author Mohsin Husen
* @author Chris White
* @author Mark Paluch
* @author Ilkang Na
* @author Christoph Strobl
* @author Peter-Josef Meisch
*/
public class DefaultResultMapperTests {
private SimpleElasticsearchMappingContext context = new SimpleElasticsearchMappingContext();
private EntityMapper entityMapper = new MappingElasticsearchConverter(context);
private DefaultResultMapper resultMapper = new DefaultResultMapper(context, entityMapper);
private SearchResponse response = mock(SearchResponse.class);
@Test
public void shouldMapAggregationsToPage() {
// given
SearchHit[] hits = { createCarHit("Ford", "Grat"), createCarHit("BMW", "Arrow") };
SearchHits searchHits = mock(SearchHits.class);
when(searchHits.getTotalHits()).thenReturn(new TotalHits(2L, TotalHits.Relation.EQUAL_TO));
when(searchHits.iterator()).thenReturn(new ArrayIterator(hits));
when(response.getHits()).thenReturn(searchHits);
Aggregations aggregations = new Aggregations(asList(createCarAggregation()));
when(response.getAggregations()).thenReturn(aggregations);
// when
AggregatedPage<Car> page = resultMapper.mapResults(response, Car.class, Pageable.unpaged());
// then
page.hasFacets();
assertThat(page.hasAggregations()).isTrue();
assertThat(page.getAggregation("Diesel").getName()).isEqualTo("Diesel");
}
@Test
public void shouldMapSearchRequestToPage() {
// given
SearchHit[] hits = { createCarHit("Ford", "Grat"), createCarHit("BMW", "Arrow") };
SearchHits searchHits = mock(SearchHits.class);
when(searchHits.getTotalHits()).thenReturn(new TotalHits(2L, TotalHits.Relation.EQUAL_TO));
when(searchHits.iterator()).thenReturn(new ArrayIterator(hits));
when(response.getHits()).thenReturn(searchHits);
// when
Page<Car> page = resultMapper.mapResults(response, Car.class, Pageable.unpaged());
// then
assertThat(page.hasContent()).isTrue();
assertThat(page.getTotalElements()).isEqualTo(2);
assertThat(page.getContent().get(0).getName()).isEqualTo("Ford");
}
@Test
public void shouldMapPartialSearchRequestToObject() {
// given
SearchHit[] hits = { createCarPartialHit("Ford", "Grat"), createCarPartialHit("BMW", "Arrow") };
SearchHits searchHits = mock(SearchHits.class);
when(searchHits.getTotalHits()).thenReturn(new TotalHits(2L, TotalHits.Relation.EQUAL_TO));
when(searchHits.iterator()).thenReturn(new ArrayIterator(hits));
when(response.getHits()).thenReturn(searchHits);
// when
Page<Car> page = resultMapper.mapResults(response, Car.class, Pageable.unpaged());
// then
assertThat(page.hasContent()).isTrue();
assertThat(page.getTotalElements()).isEqualTo(2);
assertThat(page.getContent().get(0).getName()).isEqualTo("Ford");
}
@Test
public void shouldMapGetRequestToObject() {
// given
GetResponse response = mock(GetResponse.class);
when(response.isExists()).thenReturn(true);
Map<String, Object> sourceAsMap = new HashMap<>();
sourceAsMap.put("name", "Ford");
sourceAsMap.put("model", "Grat");
when(response.getSourceAsMap()).thenReturn(sourceAsMap);
when(response.getSourceAsBytesRef()).thenReturn(new BytesArray(" "));
// when
Car result = resultMapper.mapResult(response, Car.class);
// then
assertThat(result).isNotNull();
assertThat(result.getModel()).isEqualTo("Grat");
assertThat(result.getName()).isEqualTo("Ford");
}
@Test // DATAES-281
@Ignore("fix me - UnsupportedOperation")
public void setsIdentifierOnImmutableType() {
GetResponse response = mock(GetResponse.class);
when(response.isExists()).thenReturn(true);
when(response.getSourceAsString()).thenReturn("{}");
when(response.getSourceAsBytesRef()).thenReturn(new BytesArray("{}"));
when(response.getId()).thenReturn("identifier");
ImmutableEntity result = resultMapper.mapResult(response, ImmutableEntity.class);
assertThat(result).isNotNull();
assertThat(result.getId()).isEqualTo("identifier");
}
@Test // DATAES-198
public void setsVersionFromGetResponse() {
GetResponse response = mock(GetResponse.class);
when(response.isExists()).thenReturn(true);
when(response.getSourceAsString()).thenReturn("{}");
when(response.getVersion()).thenReturn(1234L);
MappedEntity result = resultMapper.mapResult(response, MappedEntity.class);
assertThat(result).isNotNull();
assertThat(result.getVersion()).isEqualTo(1234);
}
@Test // DATAES-198
public void setsVersionFromMultiGetResponse() {
GetResponse response1 = mock(GetResponse.class);
when(response1.isExists()).thenReturn(true);
when(response1.getSourceAsString()).thenReturn("{}");
when(response1.getSourceAsBytesRef()).thenReturn(new BytesArray("{}"));
when(response1.isExists()).thenReturn(true);
when(response1.getVersion()).thenReturn(1234L);
GetResponse response2 = mock(GetResponse.class);
when(response2.isExists()).thenReturn(true);
when(response2.getSourceAsString()).thenReturn("{}");
when(response2.getSourceAsBytesRef()).thenReturn(new BytesArray("{}"));
when(response2.isExists()).thenReturn(true);
when(response2.getVersion()).thenReturn(5678L);
MultiGetResponse multiResponse = mock(MultiGetResponse.class);
when(multiResponse.getResponses()).thenReturn(new MultiGetItemResponse[] {
new MultiGetItemResponse(response1, null), new MultiGetItemResponse(response2, null) });
List<MappedEntity> results = resultMapper.mapResults(multiResponse, MappedEntity.class);
assertThat(results).isNotNull().hasSize(2);
assertThat(results.get(0).getVersion()).isEqualTo(1234);
assertThat(results.get(1).getVersion()).isEqualTo(5678);
}
@Test // DATAES-198
public void setsVersionFromSearchResponse() {
SearchHit hit1 = mock(SearchHit.class);
when(hit1.getSourceRef()).thenReturn(new BytesArray("{}"));
when(hit1.getVersion()).thenReturn(1234L);
SearchHit hit2 = mock(SearchHit.class);
when(hit2.getSourceRef()).thenReturn(new BytesArray("{}"));
when(hit2.getVersion()).thenReturn(5678L);
SearchHits searchHits = mock(SearchHits.class);
when(searchHits.getTotalHits()).thenReturn(new TotalHits(2L, TotalHits.Relation.EQUAL_TO));
when(searchHits.iterator()).thenReturn(Arrays.asList(hit1, hit2).iterator());
SearchResponse searchResponse = mock(SearchResponse.class);
when(searchResponse.getHits()).thenReturn(searchHits);
AggregatedPage<MappedEntity> results = resultMapper.mapResults(searchResponse, MappedEntity.class,
mock(Pageable.class));
assertThat(results).isNotNull();
assertThat(results.getContent().get(0).getVersion()).isEqualTo(1234);
assertThat(results.getContent().get(1).getVersion()).isEqualTo(5678);
}
private Aggregation createCarAggregation() {
Aggregation aggregation = mock(Terms.class);
when(aggregation.getName()).thenReturn("Diesel");
return aggregation;
}
private SearchHit createCarHit(String name, String model) {
SearchHit hit = mock(SearchHit.class);
String json = createJsonCar(name, model);
when(hit.getSourceAsString()).thenReturn(json);
when(hit.getSourceRef()).thenReturn(new BytesArray(json));
Map<String, Object> map = new LinkedHashMap<>();
map.put("name", name);
map.put("model", model);
when(hit.getSourceAsMap()).thenReturn(map);
return hit;
}
private SearchHit createCarPartialHit(String name, String model) {
SearchHit hit = mock(SearchHit.class);
when(hit.getSourceAsString()).thenReturn(null);
when(hit.getFields()).thenReturn(createCarFields(name, model));
when(hit.iterator()).thenReturn(createCarFields(name, model).values().iterator());
return hit;
}
private String createJsonCar(String name, String model) {
String q = "\"";
StringBuffer sb = new StringBuffer();
sb.append("{").append(q).append("name").append(q).append(":").append(q).append(name).append(q).append(",");
sb.append(q).append("model").append(q).append(":").append(q).append(model).append(q).append("}");
return sb.toString();
}
private Map<String, DocumentField> createCarFields(String name, String model) {
Map<String, DocumentField> result = new HashMap<>();
result.put("name", new DocumentField("name", asList(name)));
result.put("model", new DocumentField("model", asList(model)));
return result;
}
@Document(indexName = "test-index-immutable-internal")
@NoArgsConstructor(force = true)
@Getter
static class ImmutableEntity {
private final String id, name;
}
@Data
static class Car {
private String name;
private String model;
}
@Data
@Document(indexName = "test-index-sample-default-result-mapper", type = "test-type")
static class MappedEntity {
@Id private String id;
@Field(type = Text, store = true, fielddata = true) private String type;
@Field(type = Text, store = true, fielddata = true) private String message;
private int rate;
@ScriptedField private Double scriptedRate;
private boolean available;
private String highlightedMessage;
private GeoPoint location;
@Version private Long version;
@Score private float score;
}
}

View File

@ -29,8 +29,9 @@ import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.get.GetResult;
import org.elasticsearch.search.SearchHit;
import org.junit.Test;
import org.springframework.data.elasticsearch.Document;
import org.springframework.data.elasticsearch.SearchDocument;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.document.DocumentAdapters;
import org.springframework.data.elasticsearch.core.document.SearchDocument;
/**
* Unit tests for {@link DocumentAdapters}.

View File

@ -23,6 +23,7 @@ import lombok.Builder;
import lombok.Data;
import java.io.IOException;
import java.lang.Object;
import java.util.HashMap;
import java.util.Map;

View File

@ -35,20 +35,14 @@ import java.lang.Object;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import org.apache.commons.lang.StringUtils;
import org.assertj.core.util.Lists;
import org.elasticsearch.action.get.MultiGetItemResponse;
import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateRequestBuilder;
@ -56,22 +50,17 @@ import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.elasticsearch.index.VersionType;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Version;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.elasticsearch.ElasticsearchException;
@ -83,18 +72,13 @@ import org.springframework.data.elasticsearch.annotations.MultiField;
import org.springframework.data.elasticsearch.annotations.Score;
import org.springframework.data.elasticsearch.annotations.ScriptedField;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.data.util.CloseableIterator;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.util.ReflectionTestUtils;
/**
* Base for testing rest/transport templates
* Base for testing rest/transport templates. Contains the test common to both implementing classes.
*
* @author Rizwan Idrees
* @author Mohsin Husen
@ -116,9 +100,7 @@ import org.springframework.test.util.ReflectionTestUtils;
* @author Farid Azaza
* @author Gyula Attila Csorogi
*/
@RunWith(SpringRunner.class)
@ContextConfiguration("classpath:elasticsearch-template-test.xml")
public class ElasticsearchTemplateTests {
public abstract class ElasticsearchTemplateTests {
private static final String INDEX_NAME_SAMPLE_ENTITY = "test-index-sample-core-template";
private static final String INDEX_1_NAME = "test-index-1";
@ -126,32 +108,6 @@ public class ElasticsearchTemplateTests {
private static final String INDEX_3_NAME = "test-index-3";
private static final String TYPE_NAME = "test-type";
private final SearchResultMapper searchResultMapper = new SearchResultMapperAdapter() {
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
List<SampleEntity> result = new ArrayList<>();
for (SearchHit searchHit : response.getHits()) {
if (response.getHits().getHits().length <= 0) {
return new AggregatedPageImpl<T>(Collections.emptyList(), response.getScrollId());
}
String message = (String) searchHit.getSourceAsMap().get("message");
SampleEntity sampleEntity = new SampleEntity();
sampleEntity.setId(searchHit.getId());
sampleEntity.setMessage(message);
result.add(sampleEntity);
}
if (result.size() > 0) {
return new AggregatedPageImpl<T>((List<T>) result, response.getScrollId());
}
return new AggregatedPageImpl<T>(Collections.emptyList(), response.getScrollId());
}
};
@Autowired protected ElasticsearchOperations elasticsearchTemplate;
@Before
@ -296,21 +252,7 @@ public class ElasticsearchTemplateTests {
// when
SearchQuery query = new NativeSearchQueryBuilder().withIds(Arrays.asList(documentId, documentId2))
.withFields("message", "type").build();
List<SampleEntity> sampleEntities = elasticsearchTemplate.multiGet(query, SampleEntity.class,
new MultiGetResultMapper() {
@Override
public <T> LinkedList<T> mapResults(MultiGetResponse responses, Class<T> clazz) {
LinkedList<T> list = new LinkedList<>();
for (MultiGetItemResponse response : responses.getResponses()) {
SampleEntity entity = new SampleEntity();
entity.setId(response.getResponse().getId());
entity.setMessage((String) response.getResponse().getSource().get("message"));
entity.setType((String) response.getResponse().getSource().get("type"));
list.add((T) entity);
}
return list;
}
});
List<SampleEntity> sampleEntities = elasticsearchTemplate.multiGet(query, SampleEntity.class);
// then
assertThat(sampleEntities).hasSize(2);
@ -1012,8 +954,9 @@ public class ElasticsearchTemplateTests {
// given
String documentId = randomNumeric(5);
String message = "some test message";
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message(message)
.version(System.currentTimeMillis()).build();
String type = "some type";
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message(message).type(type)
.version(System.currentTimeMillis()).location(new GeoPoint(1.2, 3.4)).build();
IndexQuery indexQuery = getIndexQuery(sampleEntity);
@ -1021,22 +964,17 @@ public class ElasticsearchTemplateTests {
elasticsearchTemplate.refresh(SampleEntity.class);
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
.withIndices(INDEX_NAME_SAMPLE_ENTITY).withTypes(TYPE_NAME).withFields("message").build();
// when
Page<String> page = elasticsearchTemplate.queryForPage(searchQuery, String.class, new SearchResultMapperAdapter() {
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
List<String> values = new ArrayList<>();
for (SearchHit searchHit : response.getHits()) {
values.add((String) searchHit.getSourceAsMap().get("message"));
}
return new AggregatedPageImpl<>((List<T>) values);
}
});
Page<SampleEntity> page = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class);
// then
assertThat(page).isNotNull();
assertThat(page.getTotalElements()).isEqualTo(1);
assertThat(page.getContent().get(0)).isEqualTo(message);
final SampleEntity actual = page.getContent().get(0);
assertThat(actual.message).isEqualTo(message);
assertThat(actual.getType()).isNull();
assertThat(actual.getLocation()).isNull();
}
@Test
@ -1173,14 +1111,13 @@ public class ElasticsearchTemplateTests {
criteriaQuery.addFields("message");
criteriaQuery.setPageable(PageRequest.of(0, 10));
ScrolledPage<SampleEntity> scroll = elasticsearchTemplate.startScroll(1000, criteriaQuery, SampleEntity.class,
searchResultMapper);
ScrolledPage<SampleEntity> scroll = elasticsearchTemplate.startScroll(1000, criteriaQuery, SampleEntity.class);
String scrollId = scroll.getScrollId();
List<SampleEntity> sampleEntities = new ArrayList<>();
while (scroll.hasContent()) {
sampleEntities.addAll(scroll.getContent());
scrollId = scroll.getScrollId();
scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class, searchResultMapper);
scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class);
}
elasticsearchTemplate.clearScroll(scrollId);
assertThat(sampleEntities).hasSize(30);
@ -1201,14 +1138,13 @@ public class ElasticsearchTemplateTests {
.withIndices(INDEX_NAME_SAMPLE_ENTITY).withTypes(TYPE_NAME).withFields("message").withQuery(matchAllQuery())
.withPageable(PageRequest.of(0, 10)).build();
ScrolledPage<SampleEntity> scroll = elasticsearchTemplate.startScroll(1000, searchQuery, SampleEntity.class,
searchResultMapper);
ScrolledPage<SampleEntity> scroll = elasticsearchTemplate.startScroll(1000, searchQuery, SampleEntity.class);
String scrollId = scroll.getScrollId();
List<SampleEntity> sampleEntities = new ArrayList<>();
while (scroll.hasContent()) {
sampleEntities.addAll(scroll.getContent());
scrollId = scroll.getScrollId();
scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class, searchResultMapper);
scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class);
}
elasticsearchTemplate.clearScroll(scrollId);
assertThat(sampleEntities).hasSize(30);
@ -1230,14 +1166,13 @@ public class ElasticsearchTemplateTests {
criteriaQuery.addTypes(TYPE_NAME);
criteriaQuery.setPageable(PageRequest.of(0, 10));
ScrolledPage<SampleEntity> scroll = elasticsearchTemplate.startScroll(1000, criteriaQuery, SampleEntity.class,
searchResultMapper);
ScrolledPage<SampleEntity> scroll = elasticsearchTemplate.startScroll(1000, criteriaQuery, SampleEntity.class);
String scrollId = scroll.getScrollId();
List<SampleEntity> sampleEntities = new ArrayList<>();
while (scroll.hasContent()) {
sampleEntities.addAll(scroll.getContent());
scrollId = scroll.getScrollId();
scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class, searchResultMapper);
scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class);
}
elasticsearchTemplate.clearScroll(scrollId);
assertThat(sampleEntities).hasSize(30);
@ -1257,14 +1192,13 @@ public class ElasticsearchTemplateTests {
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery())
.withIndices(INDEX_NAME_SAMPLE_ENTITY).withTypes(TYPE_NAME).withPageable(PageRequest.of(0, 10)).build();
ScrolledPage<SampleEntity> scroll = elasticsearchTemplate.startScroll(1000, searchQuery, SampleEntity.class,
searchResultMapper);
ScrolledPage<SampleEntity> scroll = elasticsearchTemplate.startScroll(1000, searchQuery, SampleEntity.class);
String scrollId = scroll.getScrollId();
List<SampleEntity> sampleEntities = new ArrayList<>();
while (scroll.hasContent()) {
sampleEntities.addAll(scroll.getContent());
scrollId = scroll.getScrollId();
scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class, searchResultMapper);
scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class);
}
elasticsearchTemplate.clearScroll(scrollId);
assertThat(sampleEntities).hasSize(30);
@ -1555,167 +1489,6 @@ public class ElasticsearchTemplateTests {
assertThat(indexedEntity.getMessage()).isEqualTo(message);
}
@Test
public void shouldReturnHighlightedFieldsForGivenQueryAndFields() {
// given
String documentId = randomNumeric(5);
String actualMessage = "some test message";
String highlightedMessage = "some <em>test</em> message";
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message(actualMessage)
.version(System.currentTimeMillis()).build();
IndexQuery indexQuery = getIndexQuery(sampleEntity);
// when
elasticsearchTemplate.index(indexQuery);
elasticsearchTemplate.refresh(SampleEntity.class);
List<HighlightBuilder.Field> message = new HighlightBuilder().field("message").fields();
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("message", "test"))
.withHighlightFields(message.toArray(new HighlightBuilder.Field[message.size()])).build();
Page<SampleEntity> sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class,
new SearchResultMapperAdapter() {
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
List<SampleEntity> chunk = new ArrayList<>();
for (SearchHit searchHit : response.getHits()) {
if (response.getHits().getHits().length <= 0) {
return null;
}
SampleEntity user = new SampleEntity();
user.setId(searchHit.getId());
user.setMessage((String) searchHit.getSourceAsMap().get("message"));
user.setHighlightedMessage(searchHit.getHighlightFields().get("message").fragments()[0].toString());
chunk.add(user);
}
if (chunk.size() > 0) {
return new AggregatedPageImpl<>((List<T>) chunk);
}
return null;
}
});
// then
assertThat(sampleEntities.getContent().get(0).getHighlightedMessage()).isEqualTo(highlightedMessage);
}
@Test // DATAES-412
public void shouldReturnMultipleHighlightFields() {
// given
String documentId = randomNumeric(5);
String actualType = "some test type";
String actualMessage = "some test message";
String highlightedType = "some <em>test</em> type";
String highlightedMessage = "some <em>test</em> message";
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).type(actualType).message(actualMessage)
.version(System.currentTimeMillis()).build();
IndexQuery indexQuery = getIndexQuery(sampleEntity);
elasticsearchTemplate.index(indexQuery);
elasticsearchTemplate.refresh(SampleEntity.class);
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(boolQuery().must(termQuery("type", "test")).must(termQuery("message", "test")))
.withHighlightFields(new HighlightBuilder.Field("type"), new HighlightBuilder.Field("message")).build();
// when
elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, new SearchResultMapperAdapter() {
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
for (SearchHit searchHit : response.getHits()) {
Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
HighlightField highlightFieldType = highlightFields.get("type");
HighlightField highlightFieldMessage = highlightFields.get("message");
// then
assertThat(highlightFieldType).isNotNull();
assertThat(highlightFieldMessage).isNotNull();
assertThat(highlightFieldType.fragments()[0].toString()).isEqualTo(highlightedType);
assertThat(highlightFieldMessage.fragments()[0].toString()).isEqualTo(highlightedMessage);
}
return null;
}
});
}
@Test // DATAES-645
public void shouldReturnHighlightedFieldsInScroll() {
// given
long scrollTimeInMillis = 3000;
String documentId = randomNumeric(5);
String actualType = "some test type";
String actualMessage = "some test message";
String highlightedType = "some <em>test</em> type";
String highlightedMessage = "some <em>test</em> message";
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).type(actualType).message(actualMessage)
.version(System.currentTimeMillis()).build();
IndexQuery indexQuery = getIndexQuery(sampleEntity);
elasticsearchTemplate.index(indexQuery);
elasticsearchTemplate.refresh(SampleEntity.class);
HighlightBuilder highlightBuilder = new HighlightBuilder().field("type").field("message");
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(boolQuery().must(termQuery("type", "test")).must(termQuery("message", "test")))
.withPageable(PageRequest.of(0, 10)).withHighlightBuilder(highlightBuilder).build();
SearchResultMapper searchResultMapper = new SearchResultMapper() {
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
MappingElasticsearchConverter mappingElasticsearchConverter = new MappingElasticsearchConverter(
new SimpleElasticsearchMappingContext());
ArrayList<T> result = new ArrayList<>();
for (SearchHit searchHit : response.getHits()) {
try {
result
.add((T) mappingElasticsearchConverter.mapToObject(searchHit.getSourceAsString(), SampleEntity.class));
} catch (IOException e) {
e.printStackTrace();
}
Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
HighlightField highlightFieldType = highlightFields.get("type");
HighlightField highlightFieldMessage = highlightFields.get("message");
// then
assertThat(highlightFieldType).isNotNull();
assertThat(highlightFieldMessage).isNotNull();
assertThat(highlightFieldType.fragments()[0].toString()).isEqualTo(highlightedType);
assertThat(highlightFieldMessage.fragments()[0].toString()).isEqualTo(highlightedMessage);
}
return new AggregatedPageImpl<T>(result, pageable, response.getHits().getTotalHits().value,
response.getAggregations(), response.getScrollId(), response.getHits().getMaxScore());
}
@Override
public <T> T mapSearchHit(SearchHit searchHit, Class<T> type) {
return null;
}
};
// when
ScrolledPage<SampleEntity> scroll = elasticsearchTemplate.startScroll(scrollTimeInMillis, searchQuery,
SampleEntity.class, searchResultMapper);
while (scroll.hasContent()) {
scroll = elasticsearchTemplate.continueScroll(scroll.getScrollId(), scrollTimeInMillis, SampleEntity.class,
searchResultMapper);
}
elasticsearchTemplate.clearScroll(scroll.getScrollId());
}
@Test // DATAES-671
public void shouldPassIndicesOptionsForGivenSearchScrollQuery() {
@ -1738,13 +1511,12 @@ public class ElasticsearchTemplateTests {
List<SampleEntity> entities = new ArrayList<>();
ScrolledPage<SampleEntity> scroll = elasticsearchTemplate.startScroll(scrollTimeInMillis, searchQuery,
SampleEntity.class, searchResultMapper);
SampleEntity.class);
entities.addAll(scroll.getContent());
while (scroll.hasContent()) {
scroll = elasticsearchTemplate.continueScroll(scroll.getScrollId(), scrollTimeInMillis, SampleEntity.class,
searchResultMapper);
scroll = elasticsearchTemplate.continueScroll(scroll.getScrollId(), scrollTimeInMillis, SampleEntity.class);
entities.addAll(scroll.getContent());
}
@ -1754,84 +1526,6 @@ public class ElasticsearchTemplateTests {
assertThat(entities.size()).isGreaterThanOrEqualTo(1);
}
@Test // DATAES-479
public void shouldHonorTheHighlightBuilderOptions() {
// given
String documentId = randomNumeric(5);
String actualMessage = "some test message with <html> unsafe <script> text";
String highlightedMessage = "some <em>test</em> message with &lt;html&gt; unsafe &lt;script&gt; text";
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message(actualMessage)
.version(System.currentTimeMillis()).build();
IndexQuery indexQuery = getIndexQuery(sampleEntity);
elasticsearchTemplate.index(indexQuery);
elasticsearchTemplate.refresh(SampleEntity.class);
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("message", "test"))
.withHighlightBuilder(new HighlightBuilder().encoder("html"))
.withHighlightFields(new HighlightBuilder.Field("message")).build();
// when
elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, new SearchResultMapperAdapter() {
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
for (SearchHit searchHit : response.getHits()) {
Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
HighlightField highlightFieldMessage = highlightFields.get("message");
// then
assertThat(highlightFieldMessage).isNotNull();
assertThat(highlightFieldMessage.fragments()[0].toString()).isEqualTo(highlightedMessage);
}
return null;
}
});
}
@Test // DATAES-479
public void shouldHighlightIfBuilderSetEvenIfFieldsNotSet() {
// given
String documentId = randomNumeric(5);
String actualMessage = "some test message text";
String highlightedMessage = "some <em>test</em> message text";
SampleEntity sampleEntity = SampleEntity.builder().id(documentId).message(actualMessage)
.version(System.currentTimeMillis()).build();
IndexQuery indexQuery = getIndexQuery(sampleEntity);
elasticsearchTemplate.index(indexQuery);
elasticsearchTemplate.refresh(SampleEntity.class);
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(termQuery("message", "test"))
.withHighlightBuilder(new HighlightBuilder().field("message")).build();
// when
elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, new SearchResultMapper() {
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
for (SearchHit searchHit : response.getHits()) {
Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
HighlightField highlightFieldMessage = highlightFields.get("message");
// then
assertThat(highlightFieldMessage).isNotNull();
assertThat(highlightFieldMessage.fragments()[0].toString()).isEqualTo(highlightedMessage);
}
return null;
}
@Override
public <T> T mapSearchHit(SearchHit searchHit, Class<T> type) {
return null;
}
});
}
@Test // DATAES-487
public void shouldReturnSameEntityForMultiSearch() {
@ -1939,20 +1633,7 @@ public class ElasticsearchTemplateTests {
.withIndices(INDEX_NAME_SAMPLE_ENTITY).withTypes(TYPE_NAME).build();
// then
Page<SampleEntity> page = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class,
new SearchResultMapperAdapter() {
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
List<SampleEntity> values = new ArrayList<>();
for (SearchHit searchHit : response.getHits()) {
SampleEntity sampleEntity = new SampleEntity();
sampleEntity.setId(searchHit.getId());
sampleEntity.setMessage((String) searchHit.getSourceAsMap().get("message"));
values.add(sampleEntity);
}
return new AggregatedPageImpl<>((List<T>) values);
}
});
Page<SampleEntity> page = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class);
assertThat(page).isNotNull();
assertThat(page.getContent()).hasSize(1);
assertThat(page.getContent().get(0).getId()).isEqualTo(indexQuery.getId());
@ -2136,29 +1817,7 @@ public class ElasticsearchTemplateTests {
// then
SearchQuery searchQuery = new NativeSearchQueryBuilder().withIndices(INDEX_NAME_SAMPLE_ENTITY).withTypes(TYPE_NAME)
.withQuery(matchAllQuery()).build();
Page<Map> sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, Map.class,
new SearchResultMapperAdapter() {
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
List<Map> chunk = new ArrayList<>();
for (SearchHit searchHit : response.getHits()) {
if (response.getHits().getHits().length <= 0) {
return null;
}
Map<String, Object> person = new HashMap<>();
person.put("userId", searchHit.getSourceAsMap().get("userId"));
person.put("email", searchHit.getSourceAsMap().get("email"));
person.put("title", searchHit.getSourceAsMap().get("title"));
person.put("firstName", searchHit.getSourceAsMap().get("firstName"));
person.put("lastName", searchHit.getSourceAsMap().get("lastName"));
chunk.add(person);
}
if (chunk.size() > 0) {
return new AggregatedPageImpl<>((List<T>) chunk);
}
return null;
}
});
Page<Map> sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, Map.class);
assertThat(sampleEntities.getTotalElements()).isEqualTo(2);
List<Map> content = sampleEntities.getContent();
@ -2636,24 +2295,7 @@ public class ElasticsearchTemplateTests {
// when
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withTypes("hetro")
.withIndices(INDEX_1_NAME, INDEX_2_NAME).build();
Page<ResultAggregator> page = elasticsearchTemplate.queryForPage(searchQuery, ResultAggregator.class,
new SearchResultMapperAdapter() {
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
List<ResultAggregator> values = new ArrayList<>();
for (SearchHit searchHit : response.getHits()) {
String id = String.valueOf(searchHit.getSourceAsMap().get("id"));
String firstName = StringUtils.isNotEmpty((String) searchHit.getSourceAsMap().get("firstName"))
? (String) searchHit.getSourceAsMap().get("firstName")
: "";
String lastName = StringUtils.isNotEmpty((String) searchHit.getSourceAsMap().get("lastName"))
? (String) searchHit.getSourceAsMap().get("lastName")
: "";
values.add(new ResultAggregator(id, firstName, lastName));
}
return new AggregatedPageImpl<>((List<T>) values);
}
});
Page<ResultAggregator> page = elasticsearchTemplate.queryForPage(searchQuery, ResultAggregator.class);
assertThat(page.getTotalElements()).isEqualTo(2);
}

View File

@ -24,7 +24,6 @@ import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
@ -46,15 +45,12 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Version;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.junit.junit4.ElasticsearchVersion;
import org.springframework.data.elasticsearch.junit.junit4.ElasticsearchVersionRule;
import org.springframework.data.elasticsearch.TestUtils;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
@ -66,6 +62,8 @@ import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.data.elasticsearch.core.query.StringQuery;
import org.springframework.data.elasticsearch.junit.junit4.ElasticsearchVersion;
import org.springframework.data.elasticsearch.junit.junit4.ElasticsearchVersionRule;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.StringUtils;
@ -102,9 +100,7 @@ public class ReactiveElasticsearchTemplateTests {
restTemplate.putMapping(SampleEntity.class);
restTemplate.refresh(SampleEntity.class);
template = new ReactiveElasticsearchTemplate(TestUtils.reactiveClient(), restTemplate.getElasticsearchConverter(),
new DefaultResultMapper(new MappingElasticsearchConverter(
restTemplate.getElasticsearchConverter().getMappingContext(), new DefaultConversionService())));
template = new ReactiveElasticsearchTemplate(TestUtils.reactiveClient(), restTemplate.getElasticsearchConverter());
}
@After

View File

@ -36,9 +36,8 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.GenericConversionService;
@ -48,8 +47,8 @@ import org.springframework.data.annotation.Transient;
import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter;
import org.springframework.data.elasticsearch.Document;
import org.springframework.data.elasticsearch.annotations.GeoPointField;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
import org.springframework.data.geo.Box;
@ -95,7 +94,7 @@ public class MappingElasticsearchConverterUnitTests {
Document shotGunAsMap;
Document bigBunsCafeAsMap;
@Before
@BeforeEach
public void init() {
SimpleElasticsearchMappingContext mappingContext = new SimpleElasticsearchMappingContext();
@ -126,7 +125,8 @@ public class MappingElasticsearchConverterUnitTests {
t800AsMap.put("id", "t800");
t800AsMap.put("name", "T-800");
t800AsMap.put("gender", "MACHINE");
t800AsMap.put("_class", "org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverterUnitTests$Person");
t800AsMap.put("_class",
"org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverterUnitTests$Person");
observatoryRoad = new Address();
observatoryRoad.city = "Los Angeles";
@ -143,7 +143,8 @@ public class MappingElasticsearchConverterUnitTests {
sarahAsMap.put("id", "sarah");
sarahAsMap.put("name", "Sarah Connor");
sarahAsMap.put("gender", "MAN");
sarahAsMap.put("_class", "org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverterUnitTests$Person");
sarahAsMap.put("_class",
"org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverterUnitTests$Person");
kyleAsMap = Document.create();
kyleAsMap.put("id", "kyle");
@ -189,12 +190,13 @@ public class MappingElasticsearchConverterUnitTests {
shotGunAsMap.put("_class", ShotGun.class.getName());
}
@Test(expected = IllegalArgumentException.class)
@Test
public void shouldFailToInitializeGivenMappingContextIsNull() {
// given
assertThatThrownBy(() -> {
new MappingElasticsearchConverter(null);
}).isInstanceOf(IllegalArgumentException.class);
}
@Test
@ -228,7 +230,8 @@ public class MappingElasticsearchConverterUnitTests {
// Given
// When
String jsonResult = mappingElasticsearchConverter.mapToString(Car.builder().model(CAR_MODEL).name(CAR_NAME).build());
String jsonResult = mappingElasticsearchConverter.mapObject(Car.builder().model(CAR_MODEL).name(CAR_NAME).build())
.toJson();
// Then
assertThat(jsonResult).isEqualTo(JSON_STRING);
@ -239,9 +242,10 @@ public class MappingElasticsearchConverterUnitTests {
// Given
// When
Car result = mappingElasticsearchConverter.mapToObject(JSON_STRING, Car.class);
Car result = mappingElasticsearchConverter.mapDocument(Document.parse(JSON_STRING), Car.class);
// Then
assertThat(result).isNotNull();
assertThat(result.getName()).isEqualTo(CAR_NAME);
assertThat(result.getModel()).isEqualTo(CAR_MODEL);
}
@ -255,7 +259,7 @@ public class MappingElasticsearchConverterUnitTests {
GeoEntity geoEntity = GeoEntity.builder().pointA(point).pointB(GeoPoint.fromPoint(point)).pointC(pointAsString)
.pointD(pointAsArray).build();
// when
String jsonResult = mappingElasticsearchConverter.mapToString(geoEntity);
String jsonResult = mappingElasticsearchConverter.mapObject(geoEntity).toJson();
// then
assertThat(jsonResult).contains(pointTemplate("pointA", point));
@ -276,7 +280,7 @@ public class MappingElasticsearchConverterUnitTests {
sample.annotatedTransientProperty = "transient";
// when
String result = mappingElasticsearchConverter.mapToString(sample);
String result = mappingElasticsearchConverter.mapObject(sample).toJson();
// then
assertThat(result).contains("\"property\"");
@ -736,8 +740,7 @@ public class MappingElasticsearchConverterUnitTests {
@AllArgsConstructor
@Builder
@org.springframework.data.elasticsearch.annotations.Document(indexName = "test-index-geo-core-entity-mapper",
type = "geo-test-index", shards = 1, replicas = 0,
refreshInterval = "-1")
type = "geo-test-index", shards = 1, replicas = 0, refreshInterval = "-1")
static class GeoEntity {
@Id private String id;

View File

@ -16,13 +16,11 @@
package org.springframework.data.elasticsearch.junit.jupiter;
import org.elasticsearch.client.Client;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.config.ElasticsearchConfigurationSupport;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
import org.springframework.util.Assert;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
/**
* Configuration for Spring Data Elasticsearch using
@ -40,8 +38,8 @@ public class ElasticsearchTemplateConfiguration extends ElasticsearchConfigurati
@Bean(name = { "elasticsearchOperations", "elasticsearchTemplate" })
public ElasticsearchTemplate elasticsearchTemplate(Client elasticsearchClient,
MappingElasticsearchConverter entityMapper) {
return new ElasticsearchTemplate(elasticsearchClient, entityMapper);
ElasticsearchConverter elasticsearchConverter) {
return new ElasticsearchTemplate(elasticsearchClient, elasticsearchConverter);
}
}