Skip to content

Commit 56d4079

Browse files
committed
DATAES-34 spring-projects#17 - added option to inject custom implementation of ResultMapper
1 parent 47c82a8 commit 56d4079

15 files changed

+1018
-723
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package org.springframework.data.elasticsearch.core;
2+
3+
import org.springframework.data.elasticsearch.ElasticsearchException;
4+
5+
import java.io.IOException;
6+
7+
import static org.apache.commons.lang.StringUtils.isBlank;
8+
9+
/**
10+
* @author Artur Konczak
11+
*/
12+
public abstract class AbstractResultMapper implements ResultsMapper {
13+
14+
private EntityMapper entityMapper;
15+
16+
public AbstractResultMapper(EntityMapper entityMapper) {
17+
this.entityMapper = entityMapper;
18+
}
19+
20+
public <T> T mapEntity(String source, Class<T> clazz) {
21+
if (isBlank(source)) {
22+
return null;
23+
}
24+
try {
25+
return entityMapper.mapToObject(source, clazz);
26+
} catch (IOException e) {
27+
throw new ElasticsearchException("failed to map source [ " + source + "] to class " + clazz.getSimpleName(), e);
28+
}
29+
}
30+
31+
@Override
32+
public EntityMapper getEntityMapper() {
33+
return this.entityMapper;
34+
}
35+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package org.springframework.data.elasticsearch.core;
2+
3+
import org.elasticsearch.action.get.GetResponse;
4+
import org.elasticsearch.action.search.SearchResponse;
5+
import org.elasticsearch.search.SearchHit;
6+
import org.elasticsearch.search.facet.Facet;
7+
import org.springframework.data.domain.Pageable;
8+
import org.springframework.data.elasticsearch.core.facet.DefaultFacetMapper;
9+
import org.springframework.data.elasticsearch.core.facet.FacetResult;
10+
11+
import java.util.ArrayList;
12+
import java.util.List;
13+
14+
/**
15+
* @author Artur Konczak
16+
*/
17+
public class DefaultResultMapper extends AbstractResultMapper {
18+
19+
public DefaultResultMapper(){
20+
super(new DefaultEntityMapper());
21+
}
22+
23+
public DefaultResultMapper(EntityMapper entityMapper) {
24+
super(entityMapper);
25+
}
26+
27+
@Override
28+
public <T> FacetedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
29+
long totalHits = response.getHits().totalHits();
30+
List<T> results = new ArrayList<T>();
31+
for (SearchHit hit : response.getHits()) {
32+
if (hit != null) {
33+
results.add(mapEntity(hit.sourceAsString(), clazz));
34+
}
35+
}
36+
List<FacetResult> facets = new ArrayList<FacetResult>();
37+
if (response.getFacets() != null) {
38+
for (Facet facet : response.getFacets()) {
39+
FacetResult facetResult = DefaultFacetMapper.parse(facet);
40+
if (facetResult != null) {
41+
facets.add(facetResult);
42+
}
43+
}
44+
}
45+
46+
return new FacetedPageImpl<T>(results, pageable, totalHits, facets);
47+
}
48+
49+
@Override
50+
public <T> T mapResult(GetResponse response, Class<T> clazz) {
51+
return mapEntity(response.getSourceAsString(),clazz);
52+
}
53+
}

src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchOperations.java

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,16 @@ public interface ElasticsearchOperations {
6060
*/
6161
<T> T queryForObject(GetQuery query, Class<T> clazz);
6262

63+
/**
64+
* Execute the query against elasticsearch and return the first returned object using custom mapper
65+
*
66+
* @param query
67+
* @param clazz
68+
* @param mapper
69+
* @return the first matching object
70+
*/
71+
<T> T queryForObject(GetQuery query, Class<T> clazz, GetResultMapper mapper);
72+
6373
/**
6474
* Execute the query against elasticsearch and return the first returned object
6575
*
@@ -87,14 +97,14 @@ public interface ElasticsearchOperations {
8797
*/
8898
<T> FacetedPage<T> queryForPage(SearchQuery query, Class<T> clazz);
8999

90-
/**
91-
* Execute the query against elasticsearch and return result as {@link Page}
92-
*
93-
* @param query
94-
* @param resultsMapper
95-
* @return
96-
*/
97-
<T> FacetedPage<T> queryForPage(SearchQuery query, ResultsMapper<T> resultsMapper);
100+
/**
101+
* Execute the query against elasticsearch and return result as {@link Page} using custom mapper
102+
*
103+
* @param query
104+
* @param clazz
105+
* @return
106+
*/
107+
<T> FacetedPage<T> queryForPage(SearchQuery query, Class<T> clazz, SearchResultMapper mapper);
98108

99109
/**
100110
* Execute the query against elasticsearch and return result as {@link Page}
@@ -114,6 +124,15 @@ public interface ElasticsearchOperations {
114124
*/
115125
<T> FacetedPage<T> queryForPage(StringQuery query, Class<T> clazz);
116126

127+
/**
128+
* Execute the query against elasticsearch and return result as {@link Page} using custom mapper
129+
*
130+
* @param query
131+
* @param clazz
132+
* @return
133+
*/
134+
<T> FacetedPage<T> queryForPage(StringQuery query, Class<T> clazz, SearchResultMapper mapper);
135+
117136
/**
118137
* Execute the criteria query against elasticsearch and return result as {@link List}
119138
*
@@ -284,11 +303,11 @@ public interface ElasticsearchOperations {
284303
*
285304
* @param scrollId
286305
* @param scrollTimeInMillis
287-
* @param resultsMapper
306+
* @param clazz
288307
* @param <T>
289308
* @return
290309
*/
291-
<T> Page<T> scroll(String scrollId, long scrollTimeInMillis, ResultsMapper<T> resultsMapper);
310+
<T> Page<T> scroll(String scrollId, long scrollTimeInMillis, Class<T> clazz);
292311

293312
/**
294313
* more like this query to search for documents that are "like" a specific document.

src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java

Lines changed: 31 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -39,20 +39,16 @@
3939
import org.elasticsearch.index.query.QueryBuilder;
4040
import org.elasticsearch.index.query.QueryBuilders;
4141
import org.elasticsearch.search.SearchHit;
42-
import org.elasticsearch.search.facet.Facet;
4342
import org.elasticsearch.search.facet.FacetBuilder;
4443
import org.elasticsearch.search.highlight.HighlightBuilder;
4544
import org.elasticsearch.search.sort.SortOrder;
4645
import org.springframework.data.domain.Page;
47-
import org.springframework.data.domain.Pageable;
4846
import org.springframework.data.domain.Sort;
4947
import org.springframework.data.elasticsearch.ElasticsearchException;
5048
import org.springframework.data.elasticsearch.annotations.Document;
5149
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
5250
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
53-
import org.springframework.data.elasticsearch.core.facet.FacetMapper;
5451
import org.springframework.data.elasticsearch.core.facet.FacetRequest;
55-
import org.springframework.data.elasticsearch.core.facet.FacetResult;
5652
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
5753
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
5854
import org.springframework.data.elasticsearch.core.query.*;
@@ -86,25 +82,29 @@ public class ElasticsearchTemplate implements ElasticsearchOperations {
8682

8783
private Client client;
8884
private ElasticsearchConverter elasticsearchConverter;
89-
private EntityMapper entityMapper;
85+
private ResultsMapper resultsMapper;
9086

9187
public ElasticsearchTemplate(Client client) {
9288
this(client, null, null);
9389
}
9490

9591
public ElasticsearchTemplate(Client client, EntityMapper entityMapper) {
96-
this(client, null, entityMapper);
92+
this(client, null, new DefaultResultMapper(entityMapper));
93+
}
94+
95+
public ElasticsearchTemplate(Client client, ResultsMapper resultsMapper) {
96+
this(client, null, resultsMapper);
9797
}
9898

9999
public ElasticsearchTemplate(Client client, ElasticsearchConverter elasticsearchConverter) {
100100
this(client, elasticsearchConverter, null);
101101
}
102102

103-
public ElasticsearchTemplate(Client client, ElasticsearchConverter elasticsearchConverter, EntityMapper entityMapper) {
103+
public ElasticsearchTemplate(Client client, ElasticsearchConverter elasticsearchConverter, ResultsMapper resultsMapper) {
104104
this.client = client;
105-
this.entityMapper = (entityMapper == null) ? new DefaultEntityMapper() : entityMapper;
106105
this.elasticsearchConverter = (elasticsearchConverter == null) ? new MappingElasticsearchConverter(
107106
new SimpleElasticsearchMappingContext()) : elasticsearchConverter;
107+
this.resultsMapper = (resultsMapper == null) ? new DefaultResultMapper() : resultsMapper;
108108
}
109109

110110
@Override
@@ -134,11 +134,16 @@ public ElasticsearchConverter getElasticsearchConverter() {
134134

135135
@Override
136136
public <T> T queryForObject(GetQuery query, Class<T> clazz) {
137+
return queryForObject(query, clazz, resultsMapper);
138+
}
139+
140+
@Override
141+
public <T> T queryForObject(GetQuery query, Class<T> clazz, GetResultMapper mapper) {
137142
ElasticsearchPersistentEntity<T> persistentEntity = getPersistentEntityFor(clazz);
138143
GetResponse response = client
139144
.prepareGet(persistentEntity.getIndexName(), persistentEntity.getIndexType(), query.getId()).execute()
140145
.actionGet();
141-
return mapResult(response.getSourceAsString(), clazz);
146+
return mapper.mapResult(response, clazz);
142147
}
143148

144149
@Override
@@ -157,14 +162,13 @@ public <T> T queryForObject(StringQuery query, Class<T> clazz) {
157162

158163
@Override
159164
public <T> FacetedPage<T> queryForPage(SearchQuery query, Class<T> clazz) {
160-
SearchResponse response = doSearch(prepareSearch(query, clazz), query);
161-
return mapResults(response, clazz, query.getPageable());
165+
return queryForPage(query, clazz, resultsMapper);
162166
}
163167

164168
@Override
165-
public <T> FacetedPage<T> queryForPage(SearchQuery query, ResultsMapper<T> resultsMapper) {
166-
SearchResponse response = doSearch(prepareSearch(query), query);
167-
return resultsMapper.mapResults(response);
169+
public <T> FacetedPage<T> queryForPage(SearchQuery query, Class<T> clazz, SearchResultMapper mapper) {
170+
SearchResponse response = doSearch(prepareSearch(query, clazz), query);
171+
return mapper.mapResults(response, clazz, query.getPageable());
168172
}
169173

170174
@Override
@@ -209,13 +213,18 @@ public <T> Page<T> queryForPage(CriteriaQuery criteriaQuery, Class<T> clazz) {
209213

210214
SearchResponse response = searchRequestBuilder
211215
.execute().actionGet();
212-
return mapResults(response, clazz, criteriaQuery.getPageable());
216+
return resultsMapper.mapResults(response, clazz, criteriaQuery.getPageable());
213217
}
214218

215219
@Override
216220
public <T> FacetedPage<T> queryForPage(StringQuery query, Class<T> clazz) {
221+
return queryForPage(query, clazz, resultsMapper);
222+
}
223+
224+
@Override
225+
public <T> FacetedPage<T> queryForPage(StringQuery query, Class<T> clazz, SearchResultMapper mapper) {
217226
SearchResponse response = prepareSearch(query, clazz).setQuery(query.getSource()).execute().actionGet();
218-
return mapResults(response, clazz, query.getPageable());
227+
return mapper.mapResults(response, clazz, query.getPageable());
219228
}
220229

221230
@Override
@@ -349,10 +358,10 @@ public String scan(SearchQuery searchQuery, long scrollTimeInMillis, boolean noF
349358
}
350359

351360
@Override
352-
public <T> Page<T> scroll(String scrollId, long scrollTimeInMillis, ResultsMapper<T> resultsMapper) {
361+
public <T> Page<T> scroll(String scrollId, long scrollTimeInMillis, Class<T> clazz) {
353362
SearchResponse response = client.prepareSearchScroll(scrollId)
354363
.setScroll(TimeValue.timeValueMillis(scrollTimeInMillis)).execute().actionGet();
355-
return resultsMapper.mapResults(response);
364+
return resultsMapper.mapResults(response, clazz, null);
356365
}
357366

358367
@Override
@@ -415,7 +424,7 @@ public <T> Page<T> moreLikeThis(MoreLikeThisQuery query, Class<T> clazz) {
415424
}
416425

417426
SearchResponse response = requestBuilder.execute().actionGet();
418-
return mapResults(response, clazz, query.getPageable());
427+
return resultsMapper.mapResults(response, clazz, query.getPageable());
419428
}
420429

421430
private SearchResponse doSearch(SearchRequestBuilder searchRequest, SearchQuery searchQuery) {
@@ -513,7 +522,7 @@ private IndexRequestBuilder prepareIndex(IndexQuery query) {
513522
: query.getType();
514523

515524
IndexRequestBuilder indexRequestBuilder = client.prepareIndex(indexName, type, query.getId()).setSource(
516-
entityMapper.mapToString(query.getObject()));
525+
resultsMapper.getEntityMapper().mapToString(query.getObject()));
517526

518527
if (query.getVersion() != null) {
519528
indexRequestBuilder.setVersion(query.getVersion());
@@ -549,33 +558,6 @@ private String[] retrieveTypeFromPersistentEntity(Class clazz) {
549558
return new String[]{getPersistentEntityFor(clazz).getIndexType()};
550559
}
551560

552-
private <T> FacetedPage<T> mapResults(SearchResponse response, final Class<T> elementType, final Pageable pageable) {
553-
ResultsMapper<T> resultsMapper = new ResultsMapper<T>() {
554-
@Override
555-
public FacetedPage<T> mapResults(SearchResponse response) {
556-
long totalHits = response.getHits().totalHits();
557-
List<T> results = new ArrayList<T>();
558-
for (SearchHit hit : response.getHits()) {
559-
if (hit != null) {
560-
results.add(mapResult(hit.sourceAsString(), elementType));
561-
}
562-
}
563-
List<FacetResult> facets = new ArrayList<FacetResult>();
564-
if (response.getFacets() != null) {
565-
for (Facet facet : response.getFacets()) {
566-
FacetResult facetResult = FacetMapper.parse(facet);
567-
if (facetResult != null) {
568-
facets.add(facetResult);
569-
}
570-
}
571-
}
572-
573-
return new FacetedPageImpl<T>(results, pageable, totalHits, facets);
574-
}
575-
};
576-
return resultsMapper.mapResults(response);
577-
}
578-
579561
private List<String> extractIds(SearchResponse response) {
580562
List<String> ids = new ArrayList<String>();
581563
for (SearchHit hit : response.getHits()) {
@@ -586,24 +568,13 @@ private List<String> extractIds(SearchResponse response) {
586568
return ids;
587569
}
588570

589-
private <T> T mapResult(String source, Class<T> clazz) {
590-
if (isBlank(source)) {
591-
return null;
592-
}
593-
try {
594-
return entityMapper.mapToObject(source, clazz);
595-
} catch (IOException e) {
596-
throw new ElasticsearchException("failed to map source [ " + source + "] to class " + clazz.getSimpleName(), e);
597-
}
598-
}
599-
600571
private static String[] toArray(List<String> values) {
601572
String[] valuesAsArray = new String[values.size()];
602573
return values.toArray(valuesAsArray);
603574

604575
}
605576

606-
protected EntityMapper getEntityMapper() {
607-
return entityMapper;
577+
protected ResultsMapper getResultsMapper() {
578+
return resultsMapper;
608579
}
609580
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.springframework.data.elasticsearch.core;
2+
3+
import org.elasticsearch.action.get.GetResponse;
4+
import org.elasticsearch.action.search.SearchResponse;
5+
import org.springframework.data.domain.Pageable;
6+
7+
/**
8+
* @author Artur Konczak
9+
*/
10+
public interface GetResultMapper {
11+
12+
<T> T mapResult(GetResponse response, Class<T> clazz);
13+
14+
}

0 commit comments

Comments
 (0)