package es.official.guide.modeling;
import java.io.IOException;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequestBuilder;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.junit.Test;
import es.ESTestBase;
/**
* http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/parent-child-mapping.html
* http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/has-child.html
* http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/has-parent.html
* http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/children-agg.html
*/
public class ParentChildRelExamples extends ESTestBase {
private String indexName = "company";
private String typeBranch = "branch";
private String typeEmployee = "employee";
@Test
public void testCreateCompanyIndex() throws ElasticsearchException, IOException {
CreateIndexResponse response =
client
.admin()
.indices()
.prepareCreate(indexName)
.setSettings(
XContentFactory.jsonBuilder().field("number_of_shards", 1)
.field("number_of_replicas", 0)).execute().actionGet();
if (response.isAcknowledged()) {
System.out.println("Index creation succeeded.");
} else {
System.err.println("Index creation failed.");
}
}
@Test
public void testPuttingMappings() throws IOException {
// cannot support creating multiple mappings for types in a single call ?
// ATTENSION: BOTH setType(typeName) and the startObject(typeName) are needed, but startObject("mappings") is not needed
PutMappingRequestBuilder pmrb1 = client.admin().indices().preparePutMapping(indexName).setType(typeBranch).setSource(XContentFactory.jsonBuilder()
.startObject()
// .startObject("mappings")
.startObject(typeBranch)
.endObject()
// .endObject()
.endObject());
PutMappingRequestBuilder pmrb2 = client.admin().indices().preparePutMapping(indexName).setType(typeEmployee).setSource(XContentFactory.jsonBuilder()
.startObject()
// .startObject("mappings")
.startObject(typeEmployee)
.startObject("_parent")
.field("type", "branch")
.endObject()
.endObject()
// .endObject()
.endObject());
System.out.println(pmrb1.request().source());
System.out.println(pmrb2.request().source());
PutMappingResponse response1 = pmrb1.execute().actionGet();
PutMappingResponse response2 = pmrb2.execute().actionGet();
System.out.println(response1);
System.out.println(response2);
}
@Test
public void testIndexingParentDoc() throws IOException {
BulkRequestBuilder brb = client.prepareBulk();
brb.add(client.prepareIndex(indexName, typeBranch, "london").setSource(XContentFactory.jsonBuilder()
.startObject()
.field("name", "London Westminster")
.field("city", "London")
.field("country", "UK")
.endObject()));
brb.add(client.prepareIndex(indexName, typeBranch, "liverpool").setSource(XContentFactory.jsonBuilder()
.startObject()
.field("name", "Liverpool Central")
.field("city", "Liverpool")
.field("country", "UK")
.endObject()));
brb.add(client.prepareIndex(indexName, typeBranch, "paris").setSource(XContentFactory.jsonBuilder()
.startObject()
.field("name", "Champs Élysées")
.field("city", "Paris")
.field("country", "France")
.endObject()));
BulkResponse response = brb.execute().actionGet();
if(response.hasFailures()) {
System.err.println(response.buildFailureMessage());
} else {
System.out.println("Bulk indexing succeeded.");
}
}
/**
* Routing value is the parent value
*/
@Test
public void testIndexingChildDoc() throws IOException {
BulkRequestBuilder brb = client.prepareBulk();
// children document should have a field named "_parent", not only setRouting is not enough !!!
brb.add(client.prepareIndex(indexName, typeEmployee, "1").setRouting("london").setSource(XContentFactory.jsonBuilder()
.startObject()
.field("_parent", "london")
.field("name", "Alice Smith")
.field("dob", "1970-10-24")
.field("hobby", "hiking")
.endObject()));
brb.add(client.prepareIndex(indexName, typeEmployee, "2").setRouting("london").setSource(XContentFactory.jsonBuilder()
.startObject()
.field("_parent", "london")
.field("name", "Mark Thomas")
.field("dob", "1982-05-16")
.field("hobby", "diving")
.endObject()));
brb.add(client.prepareIndex(indexName, typeEmployee, "3").setRouting("liverpool").setSource(XContentFactory.jsonBuilder()
.startObject()
.field("_parent", "liverpool")
.field("name", "Barry Smith")
.field("dob", "1979-04-01")
.field("hobby", "hiking")
.endObject()));
brb.add(client.prepareIndex(indexName, typeEmployee, "4").setRouting("paris").setSource(XContentFactory.jsonBuilder()
.startObject()
.field("_parent", "paris")
.field("name", "Adrien Grand")
.field("dob", "1987-05-11")
.field("hobby", "horses")
.endObject()));
BulkResponse response = brb.execute().actionGet();
if(response.hasFailures()) {
System.err.println(response.buildFailureMessage());
} else {
System.out.println("Bulk indexing succeeded.");
}
}
@Test
public void testFindParentsByChildren() {
SearchResponse response = client.prepareSearch(indexName).setQuery(
// 1987-10-20 can meet the criteria
QueryBuilders.hasChildQuery(typeEmployee, QueryBuilders.rangeQuery("dob").gte("1980-01-01")))
.execute().actionGet();
// read response
System.out.println(response);
}
@Test
public void testFindParentsByChildrenMatch() {
SearchResponse response = client.prepareSearch(indexName).setQuery(
QueryBuilders.hasChildQuery(typeEmployee, QueryBuilders.matchQuery("name", "Alice Smith")).scoreType("max"))
.execute().actionGet();
// read response
System.out.println(response);
}
@Test
public void testFindParentsWithMinChildren() {
SearchResponse response = client.prepareSearch(indexName).setQuery(
QueryBuilders.hasChildQuery(typeEmployee, QueryBuilders.matchAllQuery()).minChildren(2))
.execute().actionGet();
// read response
System.out.println(response);
}
@Test
public void testFindChildrenByParent() {
SearchResponse response = client.prepareSearch(indexName).setQuery(QueryBuilders.hasParentQuery(typeBranch, QueryBuilders.matchQuery("country", "UK")))
.execute().actionGet();
// read response
System.out.println(response);
}
/**
* children agg as a direct analog to the nested agg
*/
@Test
public void testChildrenAgg() {
// how we could determine the favourite hobbies of our employees by country
// TODO: seems that ES 1.3.x does not support children aggregations
}
}