DATAES-34 #17 - added option to inject custom implementation of ResultMapper

This commit is contained in:
Artur Konczak 2013-11-17 20:25:50 +00:00
parent 47c82a8f96
commit 56d4079d81
15 changed files with 1001 additions and 706 deletions

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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
* *
@ -88,13 +98,13 @@ 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.

View File

@ -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;
} }
} }

View File

@ -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);
}

View File

@ -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();
} }

View File

@ -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);
}

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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.
}
}

View File

@ -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));
}
}

View File

@ -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();
}
}

View File

@ -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));
} }
} }

View File

@ -29,6 +29,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.SampleEntity; import org.springframework.data.elasticsearch.SampleEntity;
import org.springframework.data.elasticsearch.SampleMappingEntity; import org.springframework.data.elasticsearch.SampleMappingEntity;
@ -465,14 +466,14 @@ public class ElasticsearchTemplateTests {
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withIndices("test-index") SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withIndices("test-index")
.withTypes("test-type").withFields("message").build(); .withTypes("test-type").withFields("message").build();
// when // when
Page<String> page = elasticsearchTemplate.queryForPage(searchQuery, new ResultsMapper<String>() { Page<String> page = elasticsearchTemplate.queryForPage(searchQuery, String.class, new SearchResultMapper() {
@Override @Override
public FacetedPage<String> mapResults(SearchResponse response) { public <T> FacetedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
List<String> values = new ArrayList<String>(); List<String> values = new ArrayList<String>();
for (SearchHit searchHit : response.getHits()) { for (SearchHit searchHit : response.getHits()) {
values.add((String) searchHit.field("message").value()); values.add((String) searchHit.field("message").value());
} }
return new FacetedPageImpl<String>(values); return new FacetedPageImpl<T>((List<T>) values);
} }
}); });
// then // then
@ -543,28 +544,8 @@ public class ElasticsearchTemplateTests {
List<SampleEntity> sampleEntities = new ArrayList<SampleEntity>(); List<SampleEntity> sampleEntities = new ArrayList<SampleEntity>();
boolean hasRecords = true; boolean hasRecords = true;
while (hasRecords) { while (hasRecords) {
Page<SampleEntity> page = elasticsearchTemplate.scroll(scrollId, 5000L, new ResultsMapper<SampleEntity>() { Page<SampleEntity> page = elasticsearchTemplate.scroll(scrollId, 5000L, SampleEntity.class);
@Override if (page.hasContent()) {
public FacetedPage<SampleEntity> mapResults(SearchResponse response) {
List<SampleEntity> chunk = new ArrayList<SampleEntity>();
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.getSource().get("message"));
chunk.add(user);
}
if(chunk.size() > 0){
return new FacetedPageImpl<SampleEntity>(chunk);
}
return null;
}
});
if (page != null) {
sampleEntities.addAll(page.getContent()); sampleEntities.addAll(page.getContent());
} else { } else {
hasRecords = false; hasRecords = false;
@ -803,9 +784,9 @@ public class ElasticsearchTemplateTests {
.withHighlightFields(new HighlightBuilder.Field("message")) .withHighlightFields(new HighlightBuilder.Field("message"))
.build(); .build();
Page<SampleEntity> sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, new ResultsMapper<SampleEntity>() { Page<SampleEntity> sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class, new SearchResultMapper() {
@Override @Override
public FacetedPage<SampleEntity> mapResults(SearchResponse response) { public <T> FacetedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
List<SampleEntity> chunk = new ArrayList<SampleEntity>(); List<SampleEntity> chunk = new ArrayList<SampleEntity>();
for (SearchHit searchHit : response.getHits()) { for (SearchHit searchHit : response.getHits()) {
if (response.getHits().getHits().length <= 0) { if (response.getHits().getHits().length <= 0) {
@ -818,7 +799,7 @@ public class ElasticsearchTemplateTests {
chunk.add(user); chunk.add(user);
} }
if (chunk.size() > 0) { if (chunk.size() > 0) {
return new FacetedPageImpl<SampleEntity>(chunk); return new FacetedPageImpl<T>((List<T>) chunk);
} }
return null; return null;
} }

View File

@ -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>