Added DefaultMapper support to map only partial fields from result instead of whole source field.

This commit is contained in:
Jakub Vavrik 2013-11-19 10:44:53 +01:00
parent 3fb28de7ad
commit a76809dd0a
2 changed files with 83 additions and 1 deletions

View File

@ -1,14 +1,23 @@
package org.springframework.data.elasticsearch.core;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.base.Strings;
import org.elasticsearch.common.jackson.core.JsonEncoding;
import org.elasticsearch.common.jackson.core.JsonFactory;
import org.elasticsearch.common.jackson.core.JsonGenerator;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHitField;
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.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
@ -30,7 +39,11 @@ public class DefaultResultMapper extends AbstractResultMapper {
List<T> results = new ArrayList<T>();
for (SearchHit hit : response.getHits()) {
if (hit != null) {
results.add(mapEntity(hit.sourceAsString(), clazz));
if (!Strings.isNullOrEmpty(hit.sourceAsString())) {
results.add(mapEntity(hit.sourceAsString(), clazz));
} else {
results.add(mapEntity(hit.getFields().values(), clazz));
}
}
}
List<FacetResult> facets = new ArrayList<FacetResult>();
@ -46,6 +59,35 @@ public class DefaultResultMapper extends AbstractResultMapper {
return new FacetedPageImpl<T>(results, pageable, totalHits, facets);
}
private <T> T mapEntity(Collection<SearchHitField> values, Class<T> clazz) {
return mapEntity(buildJSONFromFields(values), clazz);
}
private String buildJSONFromFields(Collection<SearchHitField> values) {
JsonFactory nodeFactory = new JsonFactory();
try {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
JsonGenerator generator = nodeFactory.createGenerator(stream, JsonEncoding.UTF8);
generator.writeStartObject();
for (SearchHitField value : values) {
if (value.getValues().size() > 1) {
generator.writeArrayFieldStart(value.getName());
for (Object val : value.getValues()) {
generator.writeObject(val);
}
generator.writeEndArray();
} else {
generator.writeObjectField(value.getName(), value.getValue());
}
}
generator.writeEndObject();
generator.flush();
return new String(stream.toByteArray());
} catch (IOException e) {
return null;
}
}
@Override
public <T> T mapResult(GetResponse response, Class<T> clazz) {
return mapEntity(response.getSourceAsString(),clazz);

View File

@ -3,14 +3,22 @@ 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.index.get.GetField;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHitField;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.internal.InternalSearchHitField;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.data.elasticsearch.Car;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
@ -51,6 +59,24 @@ public class DefaultResultMapperTests {
assertThat(page.getContent().get(0).getName(), is("Ford"));
}
@Test
public void shouldMapPartialSearchRequestToObject() {
//Given
SearchHit[] hits = {createCarPartialHit("Ford", "Grat"), createCarPartialHit("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
@ -72,6 +98,13 @@ public class DefaultResultMapperTests {
return hit;
}
private SearchHit createCarPartialHit(String name, String model) {
SearchHit hit = mock(SearchHit.class);
when(hit.sourceAsString()).thenReturn(null);
when(hit.getFields()).thenReturn(createCarFields(name, model));
return hit;
}
private String createJsonCar(String name, String model) {
final String q = "\"";
StringBuffer sb = new StringBuffer();
@ -80,4 +113,11 @@ public class DefaultResultMapperTests {
return sb.toString();
}
private Map<String, SearchHitField> createCarFields(String name, String model) {
Map<String, SearchHitField> result = new HashMap<String, SearchHitField>();
result.put("name", new InternalSearchHitField("name", Arrays.<Object>asList(name)));
result.put("model", new InternalSearchHitField("model", Arrays.<Object>asList(model)));
return result;
}
}