From d24a92547f7ecb720af63936bd3ced6e0c0a7594 Mon Sep 17 00:00:00 2001 From: abdul Date: Thu, 17 Apr 2014 09:26:11 +0100 Subject: [PATCH] DATAES-77 - Search across different indices Add test to demonstrate searching into heterogeneous indexes and building entities of different types. In a nutshall, the responsiblity lies with the client, spring data elasticsearch cannot and should not try to discover entity types, as that would leading building an object composition logic which is not the core area of this library. With this test, we demonstrate the usage of SearchResultMapper to compose an aggregator object that holds properties from two dfferent entities, The Aggregator is declared as a document but is not indexes (This is not ideal) and we don't recommend to declare @Documents that are not indexed. Please use this as just a pointer to implement SearchResultMapper, this demostartion is not meant to be duplicated in your production systems. There are better ways to compose hetro objects from multi index searches. --- .../core/ElasticsearchTemplateTests.java | 75 ++++++++++++++++++- .../elasticsearch/entities/HetroEntity1.java | 68 +++++++++++++++++ .../elasticsearch/entities/HetroEntity2.java | 68 +++++++++++++++++ 3 files changed, 207 insertions(+), 4 deletions(-) create mode 100644 src/test/java/org/springframework/data/elasticsearch/entities/HetroEntity1.java create mode 100644 src/test/java/org/springframework/data/elasticsearch/entities/HetroEntity2.java diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java index 82a07bc2c..9ab4da6d1 100755 --- a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java @@ -23,6 +23,7 @@ import static org.junit.Assert.*; import java.util.*; +import org.apache.commons.lang.StringUtils; import org.elasticsearch.action.get.MultiGetItemResponse; import org.elasticsearch.action.get.MultiGetResponse; import org.elasticsearch.action.index.IndexRequest; @@ -35,13 +36,18 @@ import org.elasticsearch.search.sort.SortOrder; import org.junit.*; 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.elasticsearch.ElasticsearchException; +import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.builder.SampleEntityBuilder; import org.springframework.data.elasticsearch.core.query.*; +import org.springframework.data.elasticsearch.entities.HetroEntity1; +import org.springframework.data.elasticsearch.entities.HetroEntity2; import org.springframework.data.elasticsearch.entities.SampleEntity; import org.springframework.data.elasticsearch.entities.SampleMappingEntity; import org.springframework.test.context.ContextConfiguration; @@ -74,8 +80,10 @@ public class ElasticsearchTemplateTests { elasticsearchTemplate.refresh(SampleEntity.class, true); } - @After + + // @After /** // doing a cleanup to ensure that no indexes are left behind after the test run */ + /** public void after() { // it is safe to call deleteIndex as it checks for index existance before deleting it @@ -83,7 +91,7 @@ public class ElasticsearchTemplateTests { elasticsearchTemplate.deleteIndex(INDEX_1_NAME); elasticsearchTemplate.deleteIndex(INDEX_2_NAME); - } + }**/ @Test @@ -706,7 +714,6 @@ public class ElasticsearchTemplateTests { @Test public void shouldReturnListForGivenStringQuery() { // given - List indexQueries = new ArrayList(); // first document String documentId = randomNumeric(5); SampleEntity sampleEntity1 = new SampleEntityBuilder(documentId) @@ -727,7 +734,7 @@ public class ElasticsearchTemplateTests { .rate(15) .version(System.currentTimeMillis()).build(); - indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); + List indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3)); // when elasticsearchTemplate.bulkIndex(indexQueries); @@ -1556,6 +1563,47 @@ public class ElasticsearchTemplateTests { assertThat(sampleEntities.size(), is(equalTo(2))); } + @Test + /** + * This is basically a demonstration to show composing entities out of heterogeneous indexes. + */ + public void shouldComposeObjectsReturnedFromHeterogeneousIndexes() { + + // Given + + HetroEntity1 entity1 = new HetroEntity1(randomNumeric(3), "aFirstName"); + HetroEntity2 entity2 = new HetroEntity2(randomNumeric(4), "aLastName"); + + IndexQuery idxQuery1 = new IndexQueryBuilder().withIndexName(INDEX_1_NAME).withId(entity1.getId()).withObject(entity1).build(); + IndexQuery idxQuery2 = new IndexQueryBuilder().withIndexName(INDEX_2_NAME).withId(entity2.getId()).withObject(entity2).build(); + + + elasticsearchTemplate.bulkIndex(Arrays.asList(idxQuery1, idxQuery2)); + elasticsearchTemplate.refresh(INDEX_1_NAME, true); + elasticsearchTemplate.refresh(INDEX_2_NAME, true); + + // When + + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withTypes("hetro").withIndices(INDEX_1_NAME, INDEX_2_NAME).build(); + Page page = elasticsearchTemplate.queryForPage(searchQuery, ResultAggregator.class, new SearchResultMapper() { + @Override + public FacetedPage mapResults(SearchResponse response, Class clazz, Pageable pageable) { + List values = new ArrayList(); + for (SearchHit searchHit : response.getHits()) { + String id = String.valueOf(searchHit.getSource().get("id")); + String firstName = StringUtils.isNotEmpty((String)searchHit.getSource().get("firstName"))?(String)searchHit.getSource().get("firstName"):""; + String lastName = StringUtils.isNotEmpty((String)searchHit.getSource().get("lastName"))?(String)searchHit.getSource().get("lastName"):""; + values.add(new ResultAggregator(id, firstName, lastName)); + } + return new FacetedPageImpl((List) values); + } + }); + + assertThat(page.getTotalElements(), is(2l)); + + } + + private IndexQuery getIndexQuery(SampleEntity sampleEntity) { return new IndexQueryBuilder().withId(sampleEntity.getId()).withObject(sampleEntity).build(); } @@ -1567,4 +1615,23 @@ public class ElasticsearchTemplateTests { } return indexQueries; } + + @Document(indexName = INDEX_2_NAME, replicas = 0, shards = 1) + class ResultAggregator { + + private String id; + private String firstName; + private String lastName; + + ResultAggregator(String id, String firstName, String lastName) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + } + + } + + + + } diff --git a/src/test/java/org/springframework/data/elasticsearch/entities/HetroEntity1.java b/src/test/java/org/springframework/data/elasticsearch/entities/HetroEntity1.java new file mode 100644 index 000000000..41bad2d43 --- /dev/null +++ b/src/test/java/org/springframework/data/elasticsearch/entities/HetroEntity1.java @@ -0,0 +1,68 @@ +package org.springframework.data.elasticsearch.entities; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.Version; +import org.springframework.data.elasticsearch.annotations.Document; + +/** + * @author abdul. + */ +@Document(indexName = "test-index-1", type = "hetro", replicas = 0, shards = 1) +public class HetroEntity1 { + + @Id + private String id; + private String firstName; + @Version + private Long version; + + public HetroEntity1(String id, String firstName) { + this.id = id; + this.firstName = firstName; + this.version = System.currentTimeMillis(); + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public Long getVersion() { + return version; + } + + public void setVersion(Long version) { + this.version = version; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof SampleEntity)) { + return false; + } + if (this == obj) { + return true; + } + HetroEntity1 rhs = (HetroEntity1) obj; + return new EqualsBuilder().append(this.id, rhs.id).append(this.firstName, rhs.firstName).append(this.version, rhs.version).isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder().append(id).append(firstName).append(version).toHashCode(); + } + +} diff --git a/src/test/java/org/springframework/data/elasticsearch/entities/HetroEntity2.java b/src/test/java/org/springframework/data/elasticsearch/entities/HetroEntity2.java new file mode 100644 index 000000000..70218ec51 --- /dev/null +++ b/src/test/java/org/springframework/data/elasticsearch/entities/HetroEntity2.java @@ -0,0 +1,68 @@ +package org.springframework.data.elasticsearch.entities; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.Version; +import org.springframework.data.elasticsearch.annotations.Document; + +/** + * @author abdul. + */ +@Document(indexName = "test-index-2", type = "hetro", replicas = 0, shards = 1) +public class HetroEntity2 { + + @Id + private String id; + private String lastName; + @Version + private Long version; + + public HetroEntity2(String id, String lastName) { + this.id = id; + this.lastName = lastName; + this.version = System.currentTimeMillis(); + } + + public void setId(String id) { + this.id = id; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public void setVersion(Long version) { + this.version = version; + } + + public String getId() { + return id; + } + + public String getLastName() { + return lastName; + } + + public Long getVersion() { + return version; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof SampleEntity)) { + return false; + } + if (this == obj) { + return true; + } + HetroEntity2 rhs = (HetroEntity2) obj; + return new EqualsBuilder().append(this.id, rhs.id).append(this.lastName, rhs.lastName).append(this.version, rhs.version).isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder().append(id).append(lastName).append(version).toHashCode(); + } + +}