Indexing parent/child documents


(Buman) #1

Hello
I'm trying to index parent/child documents across two different index
types using the Java API. Please have a look at the code and tell me
what I'm missing for the parent mapping.

//client object is a basic local node reference -- init. not shown
here.

//parent
client.prepareIndex("house", "room",
"1").setSource(createSource("livingroom","Red",
red")).execute().actionGet();
client.prepareIndex("house", "room",
"2").setSource(createSource("familyroom","White",
"Red")).execute().actionGet();
client.prepareIndex("house", "room",
"3").setSource(createSource("kitchen","Blue",
"red")).execute().actionGet();
client.prepareIndex("house", "room",
"4").setSource(createSource("bathroom","white",
"red")).execute().actionGet();
client.prepareIndex("house", "room",
"5").setSource(createSource("garage","blue",
"red")).execute().actionGet();

//children livingroom
client.prepareIndex("house", "electronics",
"6").setSource(createSourceEl("speakers", "brown",
"green")).setParent("1").execute().actionGet();
client.prepareIndex("house", "electronics",
"7").setSource(createSourceEl("amplifier", "white",
"green")).setParent("1").execute().actionGet();
client.prepareIndex("house", "electronics",
"8").setSource(createSourceEl("bluray-player", "blue",
"orange")).setParent("1").execute().actionGet();
client.prepareIndex("house", "electronics",
"9").setSource(createSourceEl("TV", "black",
"yellow")).setParent("1").execute().actionGet();
client.prepareIndex("house", "electronics",
"10").setSource(createSourceEl("computer", "black",
"blue")).setParent("1").execute().actionGet();

    //children kitchen

client.prepareIndex("house", "kitchenstuff",
"11").setSource(createSourceEl("plates", "white",
"yellow")).setParent("3").execute().actionGet();
client.prepareIndex("house", "kitchenstuff",
"12").setSource(createSourceEl("glasses", "transparent",
"purple")).setParent("3").execute().actionGet();
client.prepareIndex("house", "kitchenstuff",
"13").setSource(createSourceEl("forks", "green",
"black")).setParent("3").execute().actionGet();

client.admin().indices().refresh(Requests.refreshRequest("house")).actionGet();

final QueryStringQueryBuilder qBuilder =
QueryBuilders.queryString("blue")
.field("color", 1.0f)
.field("color2", 1.5f);

final HasChildQueryBuilder hasChildQuery =
QueryBuilders.hasChildQuery("kitchenstuff", qBuilder);

final SearchRequestBuilder respBuilder = client.prepareSearch("house")
.setTypes("room", "electronics", "kitchenstuff")
.setSearchType(SearchType.QUERY_THEN_FETCH)
.setQuery(hasChildQuery);

SearchResponse resp = respBuilder.execute().actionGet(); //STOPS here

Q: Why am I getting the exception below, when I define the parent
mapping using IndexRequestBuilder#setParent(String parent). What am I
missing here?


org.elasticsearch.action.search.SearchPhaseExecutionException: Failed
to execute phase [query], total failure; shardFailures {[1][house][3]:
SearchParseException[[house][3]: from[-1],size[-1]: Parse Failure
[Failed to parse source [:slight_smile:
򄱵ery򈨡s_child򀺋query_string򀃢lue
fields裯
lor^1.0Icolor2^1.5񻻃typeKkitchenstuff󻻀]]]; nested:
QueryParsingException[[house] [has_child] Type [kitchenstuff] does
not have parent mapping]; }{[1][house][0]: SearchParseException[[house]
[0]: from[-1],size[-1]: Parse Failure [Failed to parse source [:slight_smile:
򄱵ery򈨡s_child򀺋query_string򀃢lue
fields裯
lor^1.0Icolor2^1.5񻻃typeKkitchenstuff󻻀]]]; nested:
QueryParsingException[[house] [has_child] Type [kitchenstuff] does
not have parent mapping]; }{[1][house][4]: SearchParseException[[house]
[4]: from[-1],size[-1]: Parse Failure [Failed to parse source [:slight_smile:
򄱵ery򈨡s_child򀺋query_string򀃢lue
fields裯
lor^1.0Icolor2^1.5񻻃typeKkitchenstuff󻻀]]]; nested:
QueryParsingException[[house] [has_child] Type [kitchenstuff] does
not have parent mapping]; }{[1][house][2]: SearchParseException[[house]
[2]: from[-1],size[-1]: Parse Failure [Failed to parse source [:slight_smile:
򄱵ery򈨡s_child򀺋query_string򀃢lue
fields裯
lor^1.0Icolor2^1.5񻻃typeKkitchenstuff󻻀]]]; nested:
QueryParsingException[[house] [has_child] Type [kitchenstuff] does
not have parent mapping]; }{[1][house][1]: SearchParseException[[house]
[1]: from[-1],size[-1]: Parse Failure [Failed to parse source [:slight_smile:
򄱵ery򈨡s_child򀺋query_string򀃢lue
fields裯
lor^1.0Icolor2^1.5񻻃typeKkitchenstuff󻻀]]]; nested:
QueryParsingException[[house] [has_child] Type [kitchenstuff] does
not have parent mapping]; }
at org.elasticsearch.action.search.type.TransportSearchTypeAction
$BaseAsyncAction.onFirstPhaseResult(TransportSearchTypeAction.java:
259)
at org.elasticsearch.action.search.type.TransportSearchTypeAction
$BaseAsyncAction$3.onFailure(TransportSearchTypeAction.java:212)
at
org.elasticsearch.search.action.SearchServiceTransportAction.sendExecuteQuery(SearchServiceTransportAction.java:
143)
at
org.elasticsearch.action.search.type.TransportSearchQueryThenFetchAction
$AsyncAction.sendExecuteFirstPhase(TransportSearchQueryThenFetchAction.java:
80)
at org.elasticsearch.action.search.type.TransportSearchTypeAction
$BaseAsyncAction.performFirstPhase(TransportSearchTypeAction.java:204)
at org.elasticsearch.action.search.type.TransportSearchTypeAction
$BaseAsyncAction.performFirstPhase(TransportSearchTypeAction.java:191)
at org.elasticsearch.action.search.type.TransportSearchTypeAction
$BaseAsyncAction$2.run(TransportSearchTypeAction.java:177)
at java.util.concurrent.ThreadPoolExecutor
$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor
$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)


(Igor Motov) #2

A couple of suggestions. Make sure that your children type have parent
field defined in the mappings. If you run curl
localhost:9200/house/_mapping you should see

    "_parent" : {
      "type" : "house"
    },

defined for both electronics and kitchenstuff types. See
http://www.elasticsearch.org/guide/reference/mapping/parent-field.html for
more details.

In the search query client.prepareSearch("house").setTypes("room",
"electronics", "kitchenstuff") you don't need to specify child types. It
should be just client.prepareSearch("house").setTypes("room")

On Monday, April 23, 2012 8:48:47 AM UTC-4, Buman wrote:

Hello
I'm trying to index parent/child documents across two different index
types using the Java API. Please have a look at the code and tell me
what I'm missing for the parent mapping.

//client object is a basic local node reference -- init. not shown
here.

//parent
client.prepareIndex("house", "room",
"1").setSource(createSource("livingroom","Red",
red")).execute().actionGet();
client.prepareIndex("house", "room",
"2").setSource(createSource("familyroom","White",
"Red")).execute().actionGet();
client.prepareIndex("house", "room",
"3").setSource(createSource("kitchen","Blue",
"red")).execute().actionGet();
client.prepareIndex("house", "room",
"4").setSource(createSource("bathroom","white",
"red")).execute().actionGet();
client.prepareIndex("house", "room",
"5").setSource(createSource("garage","blue",
"red")).execute().actionGet();

//children livingroom
client.prepareIndex("house", "electronics",
"6").setSource(createSourceEl("speakers", "brown",
"green")).setParent("1").execute().actionGet();
client.prepareIndex("house", "electronics",
"7").setSource(createSourceEl("amplifier", "white",
"green")).setParent("1").execute().actionGet();
client.prepareIndex("house", "electronics",
"8").setSource(createSourceEl("bluray-player", "blue",
"orange")).setParent("1").execute().actionGet();
client.prepareIndex("house", "electronics",
"9").setSource(createSourceEl("TV", "black",
"yellow")).setParent("1").execute().actionGet();
client.prepareIndex("house", "electronics",
"10").setSource(createSourceEl("computer", "black",
"blue")).setParent("1").execute().actionGet();

    //children kitchen 

client.prepareIndex("house", "kitchenstuff",
"11").setSource(createSourceEl("plates", "white",
"yellow")).setParent("3").execute().actionGet();
client.prepareIndex("house", "kitchenstuff",
"12").setSource(createSourceEl("glasses", "transparent",
"purple")).setParent("3").execute().actionGet();
client.prepareIndex("house", "kitchenstuff",
"13").setSource(createSourceEl("forks", "green",
"black")).setParent("3").execute().actionGet();

client.admin().indices().refresh(Requests.refreshRequest("house")).actionGet();

final QueryStringQueryBuilder qBuilder =
QueryBuilders.queryString("blue")
.field("color", 1.0f)
.field("color2", 1.5f);

final HasChildQueryBuilder hasChildQuery =
QueryBuilders.hasChildQuery("kitchenstuff", qBuilder);

final SearchRequestBuilder respBuilder = client.prepareSearch("house")
.setTypes("room", "electronics", "kitchenstuff")
.setSearchType(SearchType.QUERY_THEN_FETCH)
.setQuery(hasChildQuery);

SearchResponse resp = respBuilder.execute().actionGet(); //STOPS here

Q: Why am I getting the exception below, when I define the parent
mapping using IndexRequestBuilder#setParent(String parent). What am I
missing here?


org.elasticsearch.action.search.SearchPhaseExecutionException: Failed
to execute phase [query], total failure; shardFailures {[1][house][3]:
SearchParseException[[house][3]: from[-1],size[-1]: Parse Failure
[Failed to parse source [:slight_smile:
򄱵ery򈨡s_child򀺋query_string򀃢lue fields裯
lor^1.0Icolor2^1.5񻻃typeKkitchenstuff󻻀]]]; nested:
QueryParsingException[[house] [has_child] Type [kitchenstuff] does
not have parent mapping]; }{[1][house][0]: SearchParseException[[house]
[0]: from[-1],size[-1]: Parse Failure [Failed to parse source [:slight_smile:
򄱵ery򈨡s_child򀺋query_string򀃢lue fields裯
lor^1.0Icolor2^1.5񻻃typeKkitchenstuff󻻀]]]; nested:
QueryParsingException[[house] [has_child] Type [kitchenstuff] does
not have parent mapping]; }{[1][house][4]: SearchParseException[[house]
[4]: from[-1],size[-1]: Parse Failure [Failed to parse source [:slight_smile:
򄱵ery򈨡s_child򀺋query_string򀃢lue fields裯
lor^1.0Icolor2^1.5񻻃typeKkitchenstuff󻻀]]]; nested:
QueryParsingException[[house] [has_child] Type [kitchenstuff] does
not have parent mapping]; }{[1][house][2]: SearchParseException[[house]
[2]: from[-1],size[-1]: Parse Failure [Failed to parse source [:slight_smile:
򄱵ery򈨡s_child򀺋query_string򀃢lue fields裯
lor^1.0Icolor2^1.5񻻃typeKkitchenstuff󻻀]]]; nested:
QueryParsingException[[house] [has_child] Type [kitchenstuff] does
not have parent mapping]; }{[1][house][1]: SearchParseException[[house]
[1]: from[-1],size[-1]: Parse Failure [Failed to parse source [:slight_smile:
򄱵ery򈨡s_child򀺋query_string򀃢lue fields裯
lor^1.0Icolor2^1.5񻻃typeKkitchenstuff󻻀]]]; nested:
QueryParsingException[[house] [has_child] Type [kitchenstuff] does
not have parent mapping]; }
at org.elasticsearch.action.search.type.TransportSearchTypeAction
$BaseAsyncAction.onFirstPhaseResult(TransportSearchTypeAction.java:
259)
at org.elasticsearch.action.search.type.TransportSearchTypeAction
$BaseAsyncAction$3.onFailure(TransportSearchTypeAction.java:212)
at
org.elasticsearch.search.action.SearchServiceTransportAction.sendExecuteQuery(SearchServiceTransportAction.java:

  1. at
    org.elasticsearch.action.search.type.TransportSearchQueryThenFetchAction
    $AsyncAction.sendExecuteFirstPhase(TransportSearchQueryThenFetchAction.java:

  2. at org.elasticsearch.action.search.type.TransportSearchTypeAction 
    

$BaseAsyncAction.performFirstPhase(TransportSearchTypeAction.java:204)
at org.elasticsearch.action.search.type.TransportSearchTypeAction
$BaseAsyncAction.performFirstPhase(TransportSearchTypeAction.java:191)
at org.elasticsearch.action.search.type.TransportSearchTypeAction
$BaseAsyncAction$2.run(TransportSearchTypeAction.java:177)
at java.util.concurrent.ThreadPoolExecutor
$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor
$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)


(Buman) #3

OK, I missed that. I made this private method that I can use for both child
types:

private void putParentMapping(String parentType, String childType) throws
IOException {
final XContentBuilder mappingBuilder = XContentFactory.jsonBuilder()
.startObject()
.startObject(childType)
.startObject("_parent")
.field("type", parentType)
.endObject()
.endObject()
.endObject();

    client.admin().indices().preparePutMapping("house")
            .setType(childType).setSource(mappingBuilder)
            .execute().actionGet();
}

Looks like it working now.
Thanks Igor :slight_smile:

kl. 18:44:38 UTC+2 mandag 23. april 2012 skrev Igor Motov følgende:

A couple of suggestions. Make sure that your children type have parent
field defined in the mappings. If you run curl
localhost:9200/house/_mapping you should see

    "_parent" : {
      "type" : "house"
    },

defined for both electronics and kitchenstuff types. See
http://www.elasticsearch.org/guide/reference/mapping/parent-field.htmlfor more details.

In the search query client.prepareSearch("house").setTypes("room",
"electronics", "kitchenstuff") you don't need to specify child types. It
should be just client.prepareSearch("house").setTypes("room")


(system) #4