mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-06-23 20:42:11 +00:00
DATAES-630 - Remove GetResultMapper and friends from core package.
Original PR: #331
This commit is contained in:
parent
d4f23a50e7
commit
4e7f1ccb4b
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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.
|
||||
*
|
||||
|
@ -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,43 +1332,38 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate
|
||||
}
|
||||
|
||||
private IndexRequest prepareIndex(IndexQuery query) {
|
||||
try {
|
||||
String indexName = StringUtils.isEmpty(query.getIndexName())
|
||||
? retrieveIndexNameFromPersistentEntity(query.getObject().getClass())[0]
|
||||
: query.getIndexName();
|
||||
String type = StringUtils.isEmpty(query.getType())
|
||||
? retrieveTypeFromPersistentEntity(query.getObject().getClass())[0]
|
||||
: query.getType();
|
||||
String indexName = StringUtils.isEmpty(query.getIndexName())
|
||||
? retrieveIndexNameFromPersistentEntity(query.getObject().getClass())[0]
|
||||
: query.getIndexName();
|
||||
String type = StringUtils.isEmpty(query.getType())
|
||||
? retrieveTypeFromPersistentEntity(query.getObject().getClass())[0]
|
||||
: query.getType();
|
||||
|
||||
IndexRequest indexRequest = null;
|
||||
IndexRequest indexRequest = null;
|
||||
|
||||
if (query.getObject() != null) {
|
||||
String id = StringUtils.isEmpty(query.getId()) ? getPersistentEntityId(query.getObject()) : query.getId();
|
||||
// If we have a query id and a document id, do not ask ES to generate one.
|
||||
if (id != null) {
|
||||
indexRequest = new IndexRequest(indexName, type, id);
|
||||
} else {
|
||||
indexRequest = new IndexRequest(indexName, type);
|
||||
}
|
||||
indexRequest.source(resultsMapper.getEntityMapper().mapToString(query.getObject()),
|
||||
Requests.INDEX_CONTENT_TYPE);
|
||||
} else if (query.getSource() != null) {
|
||||
indexRequest = new IndexRequest(indexName, type, query.getId()).source(query.getSource(),
|
||||
Requests.INDEX_CONTENT_TYPE);
|
||||
if (query.getObject() != null) {
|
||||
String id = StringUtils.isEmpty(query.getId()) ? getPersistentEntityId(query.getObject()) : query.getId();
|
||||
// If we have a query id and a document id, do not ask ES to generate one.
|
||||
if (id != null) {
|
||||
indexRequest = new IndexRequest(indexName, type, id);
|
||||
} else {
|
||||
throw new ElasticsearchException(
|
||||
"object or source is null, failed to index the document [id: " + query.getId() + "]");
|
||||
indexRequest = new IndexRequest(indexName, type);
|
||||
}
|
||||
if (query.getVersion() != null) {
|
||||
indexRequest.version(query.getVersion());
|
||||
VersionType versionType = retrieveVersionTypeFromPersistentEntity(query.getObject().getClass());
|
||||
indexRequest.versionType(versionType);
|
||||
}
|
||||
|
||||
return indexRequest;
|
||||
} catch (IOException e) {
|
||||
throw new ElasticsearchException("failed to index the document [id: " + query.getId() + "]", e);
|
||||
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);
|
||||
} else {
|
||||
throw new ElasticsearchException(
|
||||
"object or source is null, failed to index the document [id: " + query.getId() + "]");
|
||||
}
|
||||
if (query.getVersion() != null) {
|
||||
indexRequest.version(query.getVersion());
|
||||
VersionType versionType = retrieveVersionTypeFromPersistentEntity(query.getObject().getClass());
|
||||
indexRequest.versionType(versionType);
|
||||
}
|
||||
|
||||
return indexRequest;
|
||||
}
|
||||
|
||||
@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));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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,43 +1106,39 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate
|
||||
}
|
||||
|
||||
private IndexRequestBuilder prepareIndex(IndexQuery query) {
|
||||
try {
|
||||
String indexName = StringUtils.isEmpty(query.getIndexName())
|
||||
? retrieveIndexNameFromPersistentEntity(query.getObject().getClass())[0]
|
||||
: query.getIndexName();
|
||||
String type = StringUtils.isEmpty(query.getType())
|
||||
? retrieveTypeFromPersistentEntity(query.getObject().getClass())[0]
|
||||
: query.getType();
|
||||
String indexName = StringUtils.isEmpty(query.getIndexName())
|
||||
? retrieveIndexNameFromPersistentEntity(query.getObject().getClass())[0]
|
||||
: query.getIndexName();
|
||||
String type = StringUtils.isEmpty(query.getType())
|
||||
? retrieveTypeFromPersistentEntity(query.getObject().getClass())[0]
|
||||
: query.getType();
|
||||
|
||||
IndexRequestBuilder indexRequestBuilder = null;
|
||||
IndexRequestBuilder indexRequestBuilder = null;
|
||||
|
||||
if (query.getObject() != null) {
|
||||
String id = StringUtils.isEmpty(query.getId()) ? getPersistentEntityId(query.getObject()) : query.getId();
|
||||
// If we have a query id and a document id, do not ask ES to generate one.
|
||||
if (id != null) {
|
||||
indexRequestBuilder = client.prepareIndex(indexName, type, id);
|
||||
} else {
|
||||
indexRequestBuilder = client.prepareIndex(indexName, type);
|
||||
}
|
||||
indexRequestBuilder.setSource(resultsMapper.getEntityMapper().mapToString(query.getObject()),
|
||||
Requests.INDEX_CONTENT_TYPE);
|
||||
} else if (query.getSource() != null) {
|
||||
indexRequestBuilder = client.prepareIndex(indexName, type, query.getId()).setSource(query.getSource(),
|
||||
Requests.INDEX_CONTENT_TYPE);
|
||||
if (query.getObject() != null) {
|
||||
String id = StringUtils.isEmpty(query.getId()) ? getPersistentEntityId(query.getObject()) : query.getId();
|
||||
// If we have a query id and a document id, do not ask ES to generate one.
|
||||
if (id != null) {
|
||||
indexRequestBuilder = client.prepareIndex(indexName, type, id);
|
||||
} else {
|
||||
throw new ElasticsearchException(
|
||||
"object or source is null, failed to index the document [id: " + query.getId() + "]");
|
||||
indexRequestBuilder = client.prepareIndex(indexName, type);
|
||||
}
|
||||
if (query.getVersion() != null) {
|
||||
indexRequestBuilder.setVersion(query.getVersion());
|
||||
VersionType versionType = retrieveVersionTypeFromPersistentEntity(query.getObject().getClass());
|
||||
indexRequestBuilder.setVersionType(versionType);
|
||||
}
|
||||
|
||||
return indexRequestBuilder;
|
||||
} catch (IOException e) {
|
||||
throw new ElasticsearchException("failed to index the document [id: " + query.getId() + "]", e);
|
||||
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(),
|
||||
Requests.INDEX_CONTENT_TYPE);
|
||||
} else {
|
||||
throw new ElasticsearchException(
|
||||
"object or source is null, failed to index the document [id: " + query.getId() + "]");
|
||||
}
|
||||
if (query.getVersion() != null) {
|
||||
indexRequestBuilder.setVersion(query.getVersion());
|
||||
VersionType versionType = retrieveVersionTypeFromPersistentEntity(query.getObject().getClass());
|
||||
indexRequestBuilder.setVersionType(versionType);
|
||||
}
|
||||
|
||||
return indexRequestBuilder;
|
||||
}
|
||||
|
||||
@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));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
return type.isInterface() || !ClassUtils.isAssignableValue(type, mappedResult)
|
||||
? getProjectionFactory().createProjection(type, mappedResult)
|
||||
: type.cast(mappedResult);
|
||||
}
|
||||
|
||||
// --> LEGACY
|
||||
@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 {
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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() {
|
@ -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() {
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
@ -1,4 +1,3 @@
|
||||
|
||||
/**
|
||||
* Infrastructure for the Elasticsearch document-to-object mapping subsystem.
|
||||
*/
|
||||
|
@ -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}.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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";
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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}.
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 <html> unsafe <script> 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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,46 +190,48 @@ public class MappingElasticsearchConverterUnitTests {
|
||||
shotGunAsMap.put("_class", ShotGun.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFailToInitializeGivenMappingContextIsNull() {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void shouldFailToInitializeGivenMappingContextIsNull() {
|
||||
// given
|
||||
assertThatThrownBy(() -> {
|
||||
new MappingElasticsearchConverter(null);
|
||||
}).isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
// given
|
||||
new MappingElasticsearchConverter(null);
|
||||
}
|
||||
@Test
|
||||
public void shouldReturnMappingContextWithWhichItWasInitialized() {
|
||||
|
||||
@Test
|
||||
public void shouldReturnMappingContextWithWhichItWasInitialized() {
|
||||
// given
|
||||
MappingContext mappingContext = new SimpleElasticsearchMappingContext();
|
||||
MappingElasticsearchConverter converter = new MappingElasticsearchConverter(mappingContext);
|
||||
|
||||
// given
|
||||
MappingContext mappingContext = new SimpleElasticsearchMappingContext();
|
||||
MappingElasticsearchConverter converter = new MappingElasticsearchConverter(mappingContext);
|
||||
// then
|
||||
assertThat(converter.getMappingContext()).isNotNull();
|
||||
assertThat(converter.getMappingContext()).isSameAs(mappingContext);
|
||||
}
|
||||
|
||||
// then
|
||||
assertThat(converter.getMappingContext()).isNotNull();
|
||||
assertThat(converter.getMappingContext()).isSameAs(mappingContext);
|
||||
}
|
||||
@Test
|
||||
public void shouldReturnDefaultConversionService() {
|
||||
|
||||
@Test
|
||||
public void shouldReturnDefaultConversionService() {
|
||||
// given
|
||||
MappingElasticsearchConverter converter = new MappingElasticsearchConverter(
|
||||
new SimpleElasticsearchMappingContext());
|
||||
|
||||
// given
|
||||
MappingElasticsearchConverter converter = new MappingElasticsearchConverter(
|
||||
new SimpleElasticsearchMappingContext());
|
||||
// when
|
||||
ConversionService conversionService = converter.getConversionService();
|
||||
|
||||
// when
|
||||
ConversionService conversionService = converter.getConversionService();
|
||||
// then
|
||||
assertThat(conversionService).isNotNull();
|
||||
}
|
||||
|
||||
// then
|
||||
assertThat(conversionService).isNotNull();
|
||||
}
|
||||
|
||||
@Test // DATAES-530
|
||||
@Test // DATAES-530
|
||||
public void shouldMapObjectToJsonString() throws IOException {
|
||||
// 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;
|
||||
|
@ -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
|
||||
@ -35,13 +33,13 @@ public class ElasticsearchTemplateConfiguration extends ElasticsearchConfigurati
|
||||
|
||||
@Bean
|
||||
public Client elasticsearchClient(ClusterConnectionInfo clusterConnectionInfo) {
|
||||
return clusterConnectionInfo.getClient();
|
||||
return clusterConnectionInfo.getClient();
|
||||
}
|
||||
|
||||
@Bean(name = { "elasticsearchOperations", "elasticsearchTemplate" })
|
||||
public ElasticsearchTemplate elasticsearchTemplate(Client elasticsearchClient,
|
||||
MappingElasticsearchConverter entityMapper) {
|
||||
return new ElasticsearchTemplate(elasticsearchClient, entityMapper);
|
||||
ElasticsearchConverter elasticsearchConverter) {
|
||||
return new ElasticsearchTemplate(elasticsearchClient, elasticsearchConverter);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -39,12 +39,12 @@ import org.springframework.data.repository.core.support.DefaultRepositoryMetadat
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ElasticsearchRepositoryFactoryTests {
|
||||
|
||||
@Mock private ElasticsearchOperations operations;
|
||||
@Mock private ElasticsearchOperations operations;
|
||||
private ElasticsearchRepositoryFactory factory;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
ElasticsearchConverter converter = new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext());
|
||||
ElasticsearchConverter converter = new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext());
|
||||
when(operations.getElasticsearchConverter()).thenReturn(converter);
|
||||
factory = new ElasticsearchRepositoryFactory(operations);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user