Skip to content

Commit d24a925

Browse files
committed
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.
1 parent 09e3e94 commit d24a925

File tree

3 files changed

+207
-4
lines changed

3 files changed

+207
-4
lines changed

src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import java.util.*;
2525

26+
import org.apache.commons.lang.StringUtils;
2627
import org.elasticsearch.action.get.MultiGetItemResponse;
2728
import org.elasticsearch.action.get.MultiGetResponse;
2829
import org.elasticsearch.action.index.IndexRequest;
@@ -35,13 +36,18 @@
3536
import org.junit.*;
3637
import org.junit.runner.RunWith;
3738
import org.springframework.beans.factory.annotation.Autowired;
39+
import org.springframework.data.annotation.Id;
40+
import org.springframework.data.annotation.Version;
3841
import org.springframework.data.domain.Page;
3942
import org.springframework.data.domain.PageRequest;
4043
import org.springframework.data.domain.Pageable;
4144
import org.springframework.data.domain.Sort;
4245
import org.springframework.data.elasticsearch.ElasticsearchException;
46+
import org.springframework.data.elasticsearch.annotations.Document;
4347
import org.springframework.data.elasticsearch.builder.SampleEntityBuilder;
4448
import org.springframework.data.elasticsearch.core.query.*;
49+
import org.springframework.data.elasticsearch.entities.HetroEntity1;
50+
import org.springframework.data.elasticsearch.entities.HetroEntity2;
4551
import org.springframework.data.elasticsearch.entities.SampleEntity;
4652
import org.springframework.data.elasticsearch.entities.SampleMappingEntity;
4753
import org.springframework.test.context.ContextConfiguration;
@@ -74,16 +80,18 @@ public void before() {
7480
elasticsearchTemplate.refresh(SampleEntity.class, true);
7581
}
7682

77-
@After
83+
84+
// @After
7885
/** // doing a cleanup to ensure that no indexes are left behind after the test run */
86+
/**
7987
public void after() {
8088
8189
// it is safe to call deleteIndex as it checks for index existance before deleting it
8290
elasticsearchTemplate.deleteIndex(INDEX_NAME);
8391
elasticsearchTemplate.deleteIndex(INDEX_1_NAME);
8492
elasticsearchTemplate.deleteIndex(INDEX_2_NAME);
8593
86-
}
94+
}**/
8795

8896

8997
@Test
@@ -706,7 +714,6 @@ public void shouldReturnListForGivenCriteria() {
706714
@Test
707715
public void shouldReturnListForGivenStringQuery() {
708716
// given
709-
List<IndexQuery> indexQueries = new ArrayList<IndexQuery>();
710717
// first document
711718
String documentId = randomNumeric(5);
712719
SampleEntity sampleEntity1 = new SampleEntityBuilder(documentId)
@@ -727,7 +734,7 @@ public void shouldReturnListForGivenStringQuery() {
727734
.rate(15)
728735
.version(System.currentTimeMillis()).build();
729736

730-
indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3));
737+
List<IndexQuery> indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3));
731738

732739
// when
733740
elasticsearchTemplate.bulkIndex(indexQueries);
@@ -1556,6 +1563,47 @@ public void shouldTestResultsAcrossMultipleIndices() {
15561563
assertThat(sampleEntities.size(), is(equalTo(2)));
15571564
}
15581565

1566+
@Test
1567+
/**
1568+
* This is basically a demonstration to show composing entities out of heterogeneous indexes.
1569+
*/
1570+
public void shouldComposeObjectsReturnedFromHeterogeneousIndexes() {
1571+
1572+
// Given
1573+
1574+
HetroEntity1 entity1 = new HetroEntity1(randomNumeric(3), "aFirstName");
1575+
HetroEntity2 entity2 = new HetroEntity2(randomNumeric(4), "aLastName");
1576+
1577+
IndexQuery idxQuery1 = new IndexQueryBuilder().withIndexName(INDEX_1_NAME).withId(entity1.getId()).withObject(entity1).build();
1578+
IndexQuery idxQuery2 = new IndexQueryBuilder().withIndexName(INDEX_2_NAME).withId(entity2.getId()).withObject(entity2).build();
1579+
1580+
1581+
elasticsearchTemplate.bulkIndex(Arrays.asList(idxQuery1, idxQuery2));
1582+
elasticsearchTemplate.refresh(INDEX_1_NAME, true);
1583+
elasticsearchTemplate.refresh(INDEX_2_NAME, true);
1584+
1585+
// When
1586+
1587+
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withTypes("hetro").withIndices(INDEX_1_NAME, INDEX_2_NAME).build();
1588+
Page<ResultAggregator> page = elasticsearchTemplate.queryForPage(searchQuery, ResultAggregator.class, new SearchResultMapper() {
1589+
@Override
1590+
public <T> FacetedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
1591+
List<ResultAggregator> values = new ArrayList<ResultAggregator>();
1592+
for (SearchHit searchHit : response.getHits()) {
1593+
String id = String.valueOf(searchHit.getSource().get("id"));
1594+
String firstName = StringUtils.isNotEmpty((String)searchHit.getSource().get("firstName"))?(String)searchHit.getSource().get("firstName"):"";
1595+
String lastName = StringUtils.isNotEmpty((String)searchHit.getSource().get("lastName"))?(String)searchHit.getSource().get("lastName"):"";
1596+
values.add(new ResultAggregator(id, firstName, lastName));
1597+
}
1598+
return new FacetedPageImpl<T>((List<T>) values);
1599+
}
1600+
});
1601+
1602+
assertThat(page.getTotalElements(), is(2l));
1603+
1604+
}
1605+
1606+
15591607
private IndexQuery getIndexQuery(SampleEntity sampleEntity) {
15601608
return new IndexQueryBuilder().withId(sampleEntity.getId()).withObject(sampleEntity).build();
15611609
}
@@ -1567,4 +1615,23 @@ private List<IndexQuery> getIndexQueries(List<SampleEntity> sampleEntities) {
15671615
}
15681616
return indexQueries;
15691617
}
1618+
1619+
@Document(indexName = INDEX_2_NAME, replicas = 0, shards = 1)
1620+
class ResultAggregator {
1621+
1622+
private String id;
1623+
private String firstName;
1624+
private String lastName;
1625+
1626+
ResultAggregator(String id, String firstName, String lastName) {
1627+
this.id = id;
1628+
this.firstName = firstName;
1629+
this.lastName = lastName;
1630+
}
1631+
1632+
}
1633+
1634+
1635+
1636+
15701637
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package org.springframework.data.elasticsearch.entities;
2+
3+
import org.apache.commons.lang.builder.EqualsBuilder;
4+
import org.apache.commons.lang.builder.HashCodeBuilder;
5+
import org.springframework.data.annotation.Id;
6+
import org.springframework.data.annotation.Version;
7+
import org.springframework.data.elasticsearch.annotations.Document;
8+
9+
/**
10+
* @author abdul.
11+
*/
12+
@Document(indexName = "test-index-1", type = "hetro", replicas = 0, shards = 1)
13+
public class HetroEntity1 {
14+
15+
@Id
16+
private String id;
17+
private String firstName;
18+
@Version
19+
private Long version;
20+
21+
public HetroEntity1(String id, String firstName) {
22+
this.id = id;
23+
this.firstName = firstName;
24+
this.version = System.currentTimeMillis();
25+
}
26+
27+
public String getId() {
28+
return id;
29+
}
30+
31+
public void setId(String id) {
32+
this.id = id;
33+
}
34+
35+
public String getFirstName() {
36+
return firstName;
37+
}
38+
39+
public void setFirstName(String firstName) {
40+
this.firstName = firstName;
41+
}
42+
43+
public Long getVersion() {
44+
return version;
45+
}
46+
47+
public void setVersion(Long version) {
48+
this.version = version;
49+
}
50+
51+
@Override
52+
public boolean equals(Object obj) {
53+
if (!(obj instanceof SampleEntity)) {
54+
return false;
55+
}
56+
if (this == obj) {
57+
return true;
58+
}
59+
HetroEntity1 rhs = (HetroEntity1) obj;
60+
return new EqualsBuilder().append(this.id, rhs.id).append(this.firstName, rhs.firstName).append(this.version, rhs.version).isEquals();
61+
}
62+
63+
@Override
64+
public int hashCode() {
65+
return new HashCodeBuilder().append(id).append(firstName).append(version).toHashCode();
66+
}
67+
68+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package org.springframework.data.elasticsearch.entities;
2+
3+
import org.apache.commons.lang.builder.EqualsBuilder;
4+
import org.apache.commons.lang.builder.HashCodeBuilder;
5+
import org.springframework.data.annotation.Id;
6+
import org.springframework.data.annotation.Version;
7+
import org.springframework.data.elasticsearch.annotations.Document;
8+
9+
/**
10+
* @author abdul.
11+
*/
12+
@Document(indexName = "test-index-2", type = "hetro", replicas = 0, shards = 1)
13+
public class HetroEntity2 {
14+
15+
@Id
16+
private String id;
17+
private String lastName;
18+
@Version
19+
private Long version;
20+
21+
public HetroEntity2(String id, String lastName) {
22+
this.id = id;
23+
this.lastName = lastName;
24+
this.version = System.currentTimeMillis();
25+
}
26+
27+
public void setId(String id) {
28+
this.id = id;
29+
}
30+
31+
public void setLastName(String lastName) {
32+
this.lastName = lastName;
33+
}
34+
35+
public void setVersion(Long version) {
36+
this.version = version;
37+
}
38+
39+
public String getId() {
40+
return id;
41+
}
42+
43+
public String getLastName() {
44+
return lastName;
45+
}
46+
47+
public Long getVersion() {
48+
return version;
49+
}
50+
51+
@Override
52+
public boolean equals(Object obj) {
53+
if (!(obj instanceof SampleEntity)) {
54+
return false;
55+
}
56+
if (this == obj) {
57+
return true;
58+
}
59+
HetroEntity2 rhs = (HetroEntity2) obj;
60+
return new EqualsBuilder().append(this.id, rhs.id).append(this.lastName, rhs.lastName).append(this.version, rhs.version).isEquals();
61+
}
62+
63+
@Override
64+
public int hashCode() {
65+
return new HashCodeBuilder().append(id).append(lastName).append(version).toHashCode();
66+
}
67+
68+
}

0 commit comments

Comments
 (0)