mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-07-12 13:23:26 +00:00
DATAES-34 #17 - added option to inject custom implementation of ResultMapper
This commit is contained in:
parent
47c82a8f96
commit
56d4079d81
@ -0,0 +1,35 @@
|
|||||||
|
package org.springframework.data.elasticsearch.core;
|
||||||
|
|
||||||
|
import org.springframework.data.elasticsearch.ElasticsearchException;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang.StringUtils.isBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Artur Konczak
|
||||||
|
*/
|
||||||
|
public abstract class AbstractResultMapper implements ResultsMapper {
|
||||||
|
|
||||||
|
private EntityMapper entityMapper;
|
||||||
|
|
||||||
|
public AbstractResultMapper(EntityMapper entityMapper) {
|
||||||
|
this.entityMapper = entityMapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T mapEntity(String source, Class<T> clazz) {
|
||||||
|
if (isBlank(source)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return entityMapper.mapToObject(source, clazz);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ElasticsearchException("failed to map source [ " + source + "] to class " + clazz.getSimpleName(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EntityMapper getEntityMapper() {
|
||||||
|
return this.entityMapper;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package org.springframework.data.elasticsearch.core;
|
||||||
|
|
||||||
|
import org.elasticsearch.action.get.GetResponse;
|
||||||
|
import org.elasticsearch.action.search.SearchResponse;
|
||||||
|
import org.elasticsearch.search.SearchHit;
|
||||||
|
import org.elasticsearch.search.facet.Facet;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.data.elasticsearch.core.facet.DefaultFacetMapper;
|
||||||
|
import org.springframework.data.elasticsearch.core.facet.FacetResult;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Artur Konczak
|
||||||
|
*/
|
||||||
|
public class DefaultResultMapper extends AbstractResultMapper {
|
||||||
|
|
||||||
|
public DefaultResultMapper(){
|
||||||
|
super(new DefaultEntityMapper());
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefaultResultMapper(EntityMapper entityMapper) {
|
||||||
|
super(entityMapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> FacetedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
|
||||||
|
long totalHits = response.getHits().totalHits();
|
||||||
|
List<T> results = new ArrayList<T>();
|
||||||
|
for (SearchHit hit : response.getHits()) {
|
||||||
|
if (hit != null) {
|
||||||
|
results.add(mapEntity(hit.sourceAsString(), clazz));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<FacetResult> facets = new ArrayList<FacetResult>();
|
||||||
|
if (response.getFacets() != null) {
|
||||||
|
for (Facet facet : response.getFacets()) {
|
||||||
|
FacetResult facetResult = DefaultFacetMapper.parse(facet);
|
||||||
|
if (facetResult != null) {
|
||||||
|
facets.add(facetResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new FacetedPageImpl<T>(results, pageable, totalHits, facets);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T mapResult(GetResponse response, Class<T> clazz) {
|
||||||
|
return mapEntity(response.getSourceAsString(),clazz);
|
||||||
|
}
|
||||||
|
}
|
@ -60,6 +60,16 @@ public interface ElasticsearchOperations {
|
|||||||
*/
|
*/
|
||||||
<T> T queryForObject(GetQuery query, Class<T> clazz);
|
<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
|
* Execute the query against elasticsearch and return the first returned object
|
||||||
*
|
*
|
||||||
@ -87,14 +97,14 @@ public interface ElasticsearchOperations {
|
|||||||
*/
|
*/
|
||||||
<T> FacetedPage<T> queryForPage(SearchQuery query, Class<T> clazz);
|
<T> FacetedPage<T> queryForPage(SearchQuery query, Class<T> clazz);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the query against elasticsearch and return result as {@link Page}
|
* Execute the query against elasticsearch and return result as {@link Page} using custom mapper
|
||||||
*
|
*
|
||||||
* @param query
|
* @param query
|
||||||
* @param resultsMapper
|
* @param clazz
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
<T> FacetedPage<T> queryForPage(SearchQuery query, ResultsMapper<T> resultsMapper);
|
<T> FacetedPage<T> queryForPage(SearchQuery query, Class<T> clazz, SearchResultMapper mapper);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the query against elasticsearch and return result as {@link Page}
|
* Execute the query against elasticsearch and return result as {@link Page}
|
||||||
@ -114,6 +124,15 @@ public interface ElasticsearchOperations {
|
|||||||
*/
|
*/
|
||||||
<T> FacetedPage<T> queryForPage(StringQuery query, Class<T> clazz);
|
<T> FacetedPage<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> FacetedPage<T> queryForPage(StringQuery query, Class<T> clazz, SearchResultMapper mapper);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the criteria query against elasticsearch and return result as {@link List}
|
* Execute the criteria query against elasticsearch and return result as {@link List}
|
||||||
*
|
*
|
||||||
@ -284,11 +303,11 @@ public interface ElasticsearchOperations {
|
|||||||
*
|
*
|
||||||
* @param scrollId
|
* @param scrollId
|
||||||
* @param scrollTimeInMillis
|
* @param scrollTimeInMillis
|
||||||
* @param resultsMapper
|
* @param clazz
|
||||||
* @param <T>
|
* @param <T>
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
<T> Page<T> scroll(String scrollId, long scrollTimeInMillis, ResultsMapper<T> resultsMapper);
|
<T> Page<T> scroll(String scrollId, long scrollTimeInMillis, Class<T> clazz);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* more like this query to search for documents that are "like" a specific document.
|
* more like this query to search for documents that are "like" a specific document.
|
||||||
|
@ -39,20 +39,16 @@ import org.elasticsearch.index.query.FilterBuilder;
|
|||||||
import org.elasticsearch.index.query.QueryBuilder;
|
import org.elasticsearch.index.query.QueryBuilder;
|
||||||
import org.elasticsearch.index.query.QueryBuilders;
|
import org.elasticsearch.index.query.QueryBuilders;
|
||||||
import org.elasticsearch.search.SearchHit;
|
import org.elasticsearch.search.SearchHit;
|
||||||
import org.elasticsearch.search.facet.Facet;
|
|
||||||
import org.elasticsearch.search.facet.FacetBuilder;
|
import org.elasticsearch.search.facet.FacetBuilder;
|
||||||
import org.elasticsearch.search.highlight.HighlightBuilder;
|
import org.elasticsearch.search.highlight.HighlightBuilder;
|
||||||
import org.elasticsearch.search.sort.SortOrder;
|
import org.elasticsearch.search.sort.SortOrder;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.data.elasticsearch.ElasticsearchException;
|
import org.springframework.data.elasticsearch.ElasticsearchException;
|
||||||
import org.springframework.data.elasticsearch.annotations.Document;
|
import org.springframework.data.elasticsearch.annotations.Document;
|
||||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||||
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
|
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
|
||||||
import org.springframework.data.elasticsearch.core.facet.FacetMapper;
|
|
||||||
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
|
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
|
||||||
import org.springframework.data.elasticsearch.core.facet.FacetResult;
|
|
||||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
||||||
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
|
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
|
||||||
import org.springframework.data.elasticsearch.core.query.*;
|
import org.springframework.data.elasticsearch.core.query.*;
|
||||||
@ -86,25 +82,29 @@ public class ElasticsearchTemplate implements ElasticsearchOperations {
|
|||||||
|
|
||||||
private Client client;
|
private Client client;
|
||||||
private ElasticsearchConverter elasticsearchConverter;
|
private ElasticsearchConverter elasticsearchConverter;
|
||||||
private EntityMapper entityMapper;
|
private ResultsMapper resultsMapper;
|
||||||
|
|
||||||
public ElasticsearchTemplate(Client client) {
|
public ElasticsearchTemplate(Client client) {
|
||||||
this(client, null, null);
|
this(client, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ElasticsearchTemplate(Client client, EntityMapper entityMapper) {
|
public ElasticsearchTemplate(Client client, EntityMapper entityMapper) {
|
||||||
this(client, null, entityMapper);
|
this(client, null, new DefaultResultMapper(entityMapper));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ElasticsearchTemplate(Client client, ResultsMapper resultsMapper) {
|
||||||
|
this(client, null, resultsMapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ElasticsearchTemplate(Client client, ElasticsearchConverter elasticsearchConverter) {
|
public ElasticsearchTemplate(Client client, ElasticsearchConverter elasticsearchConverter) {
|
||||||
this(client, elasticsearchConverter, null);
|
this(client, elasticsearchConverter, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ElasticsearchTemplate(Client client, ElasticsearchConverter elasticsearchConverter, EntityMapper entityMapper) {
|
public ElasticsearchTemplate(Client client, ElasticsearchConverter elasticsearchConverter, ResultsMapper resultsMapper) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.entityMapper = (entityMapper == null) ? new DefaultEntityMapper() : entityMapper;
|
|
||||||
this.elasticsearchConverter = (elasticsearchConverter == null) ? new MappingElasticsearchConverter(
|
this.elasticsearchConverter = (elasticsearchConverter == null) ? new MappingElasticsearchConverter(
|
||||||
new SimpleElasticsearchMappingContext()) : elasticsearchConverter;
|
new SimpleElasticsearchMappingContext()) : elasticsearchConverter;
|
||||||
|
this.resultsMapper = (resultsMapper == null) ? new DefaultResultMapper() : resultsMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -134,11 +134,16 @@ public class ElasticsearchTemplate implements ElasticsearchOperations {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T queryForObject(GetQuery query, Class<T> clazz) {
|
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);
|
ElasticsearchPersistentEntity<T> persistentEntity = getPersistentEntityFor(clazz);
|
||||||
GetResponse response = client
|
GetResponse response = client
|
||||||
.prepareGet(persistentEntity.getIndexName(), persistentEntity.getIndexType(), query.getId()).execute()
|
.prepareGet(persistentEntity.getIndexName(), persistentEntity.getIndexType(), query.getId()).execute()
|
||||||
.actionGet();
|
.actionGet();
|
||||||
return mapResult(response.getSourceAsString(), clazz);
|
return mapper.mapResult(response, clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -157,14 +162,13 @@ public class ElasticsearchTemplate implements ElasticsearchOperations {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> FacetedPage<T> queryForPage(SearchQuery query, Class<T> clazz) {
|
public <T> FacetedPage<T> queryForPage(SearchQuery query, Class<T> clazz) {
|
||||||
SearchResponse response = doSearch(prepareSearch(query, clazz), query);
|
return queryForPage(query, clazz, resultsMapper);
|
||||||
return mapResults(response, clazz, query.getPageable());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> FacetedPage<T> queryForPage(SearchQuery query, ResultsMapper<T> resultsMapper) {
|
public <T> FacetedPage<T> queryForPage(SearchQuery query, Class<T> clazz, SearchResultMapper mapper) {
|
||||||
SearchResponse response = doSearch(prepareSearch(query), query);
|
SearchResponse response = doSearch(prepareSearch(query, clazz), query);
|
||||||
return resultsMapper.mapResults(response);
|
return mapper.mapResults(response, clazz, query.getPageable());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -209,13 +213,18 @@ public class ElasticsearchTemplate implements ElasticsearchOperations {
|
|||||||
|
|
||||||
SearchResponse response = searchRequestBuilder
|
SearchResponse response = searchRequestBuilder
|
||||||
.execute().actionGet();
|
.execute().actionGet();
|
||||||
return mapResults(response, clazz, criteriaQuery.getPageable());
|
return resultsMapper.mapResults(response, clazz, criteriaQuery.getPageable());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> FacetedPage<T> queryForPage(StringQuery query, Class<T> clazz) {
|
public <T> FacetedPage<T> queryForPage(StringQuery query, Class<T> clazz) {
|
||||||
|
return queryForPage(query, clazz, resultsMapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> FacetedPage<T> queryForPage(StringQuery query, Class<T> clazz, SearchResultMapper mapper) {
|
||||||
SearchResponse response = prepareSearch(query, clazz).setQuery(query.getSource()).execute().actionGet();
|
SearchResponse response = prepareSearch(query, clazz).setQuery(query.getSource()).execute().actionGet();
|
||||||
return mapResults(response, clazz, query.getPageable());
|
return mapper.mapResults(response, clazz, query.getPageable());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -349,10 +358,10 @@ public class ElasticsearchTemplate implements ElasticsearchOperations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> Page<T> scroll(String scrollId, long scrollTimeInMillis, ResultsMapper<T> resultsMapper) {
|
public <T> Page<T> scroll(String scrollId, long scrollTimeInMillis, Class<T> clazz) {
|
||||||
SearchResponse response = client.prepareSearchScroll(scrollId)
|
SearchResponse response = client.prepareSearchScroll(scrollId)
|
||||||
.setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)).execute().actionGet();
|
.setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)).execute().actionGet();
|
||||||
return resultsMapper.mapResults(response);
|
return resultsMapper.mapResults(response, clazz, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -415,7 +424,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SearchResponse response = requestBuilder.execute().actionGet();
|
SearchResponse response = requestBuilder.execute().actionGet();
|
||||||
return mapResults(response, clazz, query.getPageable());
|
return resultsMapper.mapResults(response, clazz, query.getPageable());
|
||||||
}
|
}
|
||||||
|
|
||||||
private SearchResponse doSearch(SearchRequestBuilder searchRequest, SearchQuery searchQuery) {
|
private SearchResponse doSearch(SearchRequestBuilder searchRequest, SearchQuery searchQuery) {
|
||||||
@ -513,7 +522,7 @@ public class ElasticsearchTemplate implements ElasticsearchOperations {
|
|||||||
: query.getType();
|
: query.getType();
|
||||||
|
|
||||||
IndexRequestBuilder indexRequestBuilder = client.prepareIndex(indexName, type, query.getId()).setSource(
|
IndexRequestBuilder indexRequestBuilder = client.prepareIndex(indexName, type, query.getId()).setSource(
|
||||||
entityMapper.mapToString(query.getObject()));
|
resultsMapper.getEntityMapper().mapToString(query.getObject()));
|
||||||
|
|
||||||
if (query.getVersion() != null) {
|
if (query.getVersion() != null) {
|
||||||
indexRequestBuilder.setVersion(query.getVersion());
|
indexRequestBuilder.setVersion(query.getVersion());
|
||||||
@ -549,33 +558,6 @@ public class ElasticsearchTemplate implements ElasticsearchOperations {
|
|||||||
return new String[]{getPersistentEntityFor(clazz).getIndexType()};
|
return new String[]{getPersistentEntityFor(clazz).getIndexType()};
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> FacetedPage<T> mapResults(SearchResponse response, final Class<T> elementType, final Pageable pageable) {
|
|
||||||
ResultsMapper<T> resultsMapper = new ResultsMapper<T>() {
|
|
||||||
@Override
|
|
||||||
public FacetedPage<T> mapResults(SearchResponse response) {
|
|
||||||
long totalHits = response.getHits().totalHits();
|
|
||||||
List<T> results = new ArrayList<T>();
|
|
||||||
for (SearchHit hit : response.getHits()) {
|
|
||||||
if (hit != null) {
|
|
||||||
results.add(mapResult(hit.sourceAsString(), elementType));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
List<FacetResult> facets = new ArrayList<FacetResult>();
|
|
||||||
if (response.getFacets() != null) {
|
|
||||||
for (Facet facet : response.getFacets()) {
|
|
||||||
FacetResult facetResult = FacetMapper.parse(facet);
|
|
||||||
if (facetResult != null) {
|
|
||||||
facets.add(facetResult);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new FacetedPageImpl<T>(results, pageable, totalHits, facets);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return resultsMapper.mapResults(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> extractIds(SearchResponse response) {
|
private List<String> extractIds(SearchResponse response) {
|
||||||
List<String> ids = new ArrayList<String>();
|
List<String> ids = new ArrayList<String>();
|
||||||
for (SearchHit hit : response.getHits()) {
|
for (SearchHit hit : response.getHits()) {
|
||||||
@ -586,24 +568,13 @@ public class ElasticsearchTemplate implements ElasticsearchOperations {
|
|||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> T mapResult(String source, Class<T> clazz) {
|
|
||||||
if (isBlank(source)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return entityMapper.mapToObject(source, clazz);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new ElasticsearchException("failed to map source [ " + source + "] to class " + clazz.getSimpleName(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String[] toArray(List<String> values) {
|
private static String[] toArray(List<String> values) {
|
||||||
String[] valuesAsArray = new String[values.size()];
|
String[] valuesAsArray = new String[values.size()];
|
||||||
return values.toArray(valuesAsArray);
|
return values.toArray(valuesAsArray);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected EntityMapper getEntityMapper() {
|
protected ResultsMapper getResultsMapper() {
|
||||||
return entityMapper;
|
return resultsMapper;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
package org.springframework.data.elasticsearch.core;
|
||||||
|
|
||||||
|
import org.elasticsearch.action.get.GetResponse;
|
||||||
|
import org.elasticsearch.action.search.SearchResponse;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Artur Konczak
|
||||||
|
*/
|
||||||
|
public interface GetResultMapper {
|
||||||
|
|
||||||
|
<T> T mapResult(GetResponse response, Class<T> clazz);
|
||||||
|
|
||||||
|
}
|
@ -15,22 +15,16 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.elasticsearch.core;
|
package org.springframework.data.elasticsearch.core;
|
||||||
|
|
||||||
import org.elasticsearch.action.search.SearchResponse;
|
|
||||||
import org.springframework.data.domain.Page;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ResultsMapper
|
* ResultsMapper
|
||||||
*
|
*
|
||||||
* @param <T>
|
|
||||||
*
|
|
||||||
* @author Rizwan Idrees
|
* @author Rizwan Idrees
|
||||||
* @author Mohsin Husen
|
* @author Mohsin Husen
|
||||||
* @author Artur Konczak
|
* @author Artur Konczak
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public interface ResultsMapper<T> {
|
public interface ResultsMapper extends SearchResultMapper, GetResultMapper {
|
||||||
|
|
||||||
FacetedPage<T> mapResults(SearchResponse response);
|
EntityMapper getEntityMapper();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
package org.springframework.data.elasticsearch.core;
|
||||||
|
|
||||||
|
import org.elasticsearch.action.search.SearchResponse;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Artur Konczak
|
||||||
|
*/
|
||||||
|
public interface SearchResultMapper {
|
||||||
|
|
||||||
|
<T> FacetedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable);
|
||||||
|
|
||||||
|
}
|
@ -14,7 +14,7 @@ import java.util.List;
|
|||||||
* @author Artur Konczak
|
* @author Artur Konczak
|
||||||
* @author Petar Tahchiev
|
* @author Petar Tahchiev
|
||||||
*/
|
*/
|
||||||
public class FacetMapper {
|
public class DefaultFacetMapper {
|
||||||
|
|
||||||
public static FacetResult parse(Facet facet) {
|
public static FacetResult parse(Facet facet) {
|
||||||
if (facet instanceof TermsFacet) {
|
if (facet instanceof TermsFacet) {
|
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.springframework.data.elasticsearch;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Artur Konczak
|
||||||
|
*/
|
||||||
|
public class CarBuilder {
|
||||||
|
|
||||||
|
private Car car = new Car();
|
||||||
|
|
||||||
|
public CarBuilder name(String name) {
|
||||||
|
car.setName(name);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CarBuilder model(String model) {
|
||||||
|
car.setModel(model);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Car build(){
|
||||||
|
return car;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package org.springframework.data.elasticsearch.core;
|
||||||
|
|
||||||
|
import org.elasticsearch.action.get.GetResponse;
|
||||||
|
import org.elasticsearch.action.search.SearchResponse;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: dead
|
||||||
|
* Date: 11/11/13
|
||||||
|
* Time: 17:37
|
||||||
|
*/
|
||||||
|
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> FacetedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
|
||||||
|
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
package org.springframework.data.elasticsearch.core;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.data.elasticsearch.Car;
|
||||||
|
import org.springframework.data.elasticsearch.CarBuilder;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Artur Konczak
|
||||||
|
*/
|
||||||
|
public class DefaultEntityMapperTests {
|
||||||
|
|
||||||
|
public static final String JSON_STRING = "{\"name\":\"Grat\",\"model\":\"Ford\"}";
|
||||||
|
public static final String CAR_MODEL = "Ford";
|
||||||
|
public static final String CAR_NAME = "Grat";
|
||||||
|
DefaultEntityMapper entityMapper;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void init(){
|
||||||
|
entityMapper = new DefaultEntityMapper();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldMapObjectToJsonString() throws IOException {
|
||||||
|
//Given
|
||||||
|
|
||||||
|
//When
|
||||||
|
String jsonResult = entityMapper.mapToString(new CarBuilder().model(CAR_MODEL).name(CAR_NAME).build());
|
||||||
|
|
||||||
|
//Then
|
||||||
|
assertThat(jsonResult, is(JSON_STRING));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldMapJsonStringToObject() throws IOException {
|
||||||
|
//Given
|
||||||
|
|
||||||
|
//When
|
||||||
|
Car result = entityMapper.mapToObject(JSON_STRING,Car.class);
|
||||||
|
|
||||||
|
//Then
|
||||||
|
assertThat(result.getName(),is(CAR_NAME));
|
||||||
|
assertThat(result.getModel(),is(CAR_MODEL));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
package org.springframework.data.elasticsearch.core;
|
||||||
|
|
||||||
|
import org.apache.commons.collections.iterators.ArrayIterator;
|
||||||
|
import org.elasticsearch.action.get.GetResponse;
|
||||||
|
import org.elasticsearch.action.search.SearchResponse;
|
||||||
|
import org.elasticsearch.search.SearchHit;
|
||||||
|
import org.elasticsearch.search.SearchHits;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
import org.springframework.data.elasticsearch.Car;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.hamcrest.Matchers.notNullValue;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Artur Konczak
|
||||||
|
*/
|
||||||
|
public class DefaultResultMapperTests {
|
||||||
|
|
||||||
|
private DefaultResultMapper resultMapper;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private SearchResponse response;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void init() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
resultMapper = new DefaultResultMapper();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldMapSearchRequestToPage() {
|
||||||
|
//Given
|
||||||
|
SearchHit[] hits = {createCarHit("Ford", "Grat"), createCarHit("BMW", "Arrow")};
|
||||||
|
SearchHits searchHits = mock(SearchHits.class);
|
||||||
|
when(searchHits.totalHits()).thenReturn(2L);
|
||||||
|
when(searchHits.iterator()).thenReturn(new ArrayIterator(hits));
|
||||||
|
when(response.getHits()).thenReturn(searchHits);
|
||||||
|
|
||||||
|
//When
|
||||||
|
FacetedPage<Car> page = resultMapper.mapResults(response, Car.class, null);
|
||||||
|
|
||||||
|
//Then
|
||||||
|
assertThat(page.hasContent(), is(true));
|
||||||
|
assertThat(page.getTotalElements(), is(2L));
|
||||||
|
assertThat(page.getContent().get(0).getName(), is("Ford"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldMapGetRequestToObject() {
|
||||||
|
//Given
|
||||||
|
GetResponse response = mock(GetResponse.class);
|
||||||
|
when(response.getSourceAsString()).thenReturn(createJsonCar("Ford", "Grat"));
|
||||||
|
|
||||||
|
//When
|
||||||
|
Car result = resultMapper.mapResult(response, Car.class);
|
||||||
|
|
||||||
|
//Then
|
||||||
|
assertThat(result, notNullValue());
|
||||||
|
assertThat(result.getModel(), is("Grat"));
|
||||||
|
assertThat(result.getName(), is("Ford"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private SearchHit createCarHit(String name, String model) {
|
||||||
|
SearchHit hit = mock(SearchHit.class);
|
||||||
|
when(hit.sourceAsString()).thenReturn(createJsonCar(name, model));
|
||||||
|
return hit;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String createJsonCar(String name, String model) {
|
||||||
|
final 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -37,12 +37,16 @@ public class ElasticsearchTemplateCustomMapperTests {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private EntityMapper entityMapper;
|
private EntityMapper entityMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ResultsMapper resultsMapper;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldUseCustomMapper() {
|
public void shouldUseCustomMapper() {
|
||||||
//given
|
//given
|
||||||
//when
|
//when
|
||||||
//them
|
//them
|
||||||
assertThat(elasticsearchTemplate.getEntityMapper(), is(entityMapper));
|
assertThat(elasticsearchTemplate.getResultsMapper(), is(resultsMapper));
|
||||||
|
assertThat(elasticsearchTemplate.getResultsMapper().getEntityMapper(), is(entityMapper));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -10,9 +10,13 @@
|
|||||||
<bean name="elasticsearchTemplate"
|
<bean name="elasticsearchTemplate"
|
||||||
class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
|
class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
|
||||||
<constructor-arg name="client" ref="client"/>
|
<constructor-arg name="client" ref="client"/>
|
||||||
<constructor-arg name="entityMapper" ref="entityMapper"/>
|
<constructor-arg name="resultsMapper" ref="resultMapper"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean name="entityMapper" class="org.springframework.data.elasticsearch.core.CustomEntityMapper"/>
|
<bean name="entityMapper" class="org.springframework.data.elasticsearch.core.CustomEntityMapper"/>
|
||||||
|
|
||||||
|
<bean name="resultMapper" class="org.springframework.data.elasticsearch.core.CustomResultMapper">
|
||||||
|
<constructor-arg ref="entityMapper"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
Loading…
x
Reference in New Issue
Block a user