diff --git a/src/main/java/org/elasticsearch/search/fetch/FetchPhase.java b/src/main/java/org/elasticsearch/search/fetch/FetchPhase.java index d41e7e3256b0b..086dff6b1e6ac 100644 --- a/src/main/java/org/elasticsearch/search/fetch/FetchPhase.java +++ b/src/main/java/org/elasticsearch/search/fetch/FetchPhase.java @@ -367,23 +367,23 @@ private Map getSearchFields(SearchContext context, int n private InternalSearchHit.InternalNestedIdentity getInternalNestedIdentity(SearchContext context, int nestedSubDocId, AtomicReaderContext subReaderContext, DocumentMapper documentMapper, ObjectMapper nestedObjectMapper) throws IOException { int currentParent = nestedSubDocId; + StringBuilder objectFieldPrefix = new StringBuilder(); + ObjectMapper current = nestedObjectMapper; ObjectMapper nestedParentObjectMapper; InternalSearchHit.InternalNestedIdentity nestedIdentity = null; do { - String field; - Filter parentFilter; - nestedParentObjectMapper = documentMapper.findParentObjectMapper(nestedObjectMapper); + String field = nestedObjectMapper.name(); + nestedParentObjectMapper = documentMapper.findParentObjectMapper(current); + + final Filter parentFilter; if (nestedParentObjectMapper != null) { - field = nestedObjectMapper.name(); if (!nestedParentObjectMapper.nested().isNested()) { - nestedObjectMapper = nestedParentObjectMapper; - // all right, the parent is a normal object field, so this is the best identiy we can give for that: - nestedIdentity = new InternalSearchHit.InternalNestedIdentity(field, 0, nestedIdentity); + objectFieldPrefix.append(nestedParentObjectMapper.name()).append('.'); + current = nestedParentObjectMapper; continue; } parentFilter = nestedParentObjectMapper.nestedTypeFilter(); } else { - field = nestedObjectMapper.fullPath(); parentFilter = NonNestedDocsFilter.INSTANCE; } @@ -395,7 +395,11 @@ private InternalSearchHit.InternalNestedIdentity getInternalNestedIdentity(Searc offset++; } currentParent = nextParent; - nestedObjectMapper = nestedParentObjectMapper; + nestedObjectMapper = current = nestedParentObjectMapper; + if (objectFieldPrefix.length() > 0) { + field = objectFieldPrefix.append(field).toString(); + objectFieldPrefix = new StringBuilder(); + } nestedIdentity = new InternalSearchHit.InternalNestedIdentity(field, offset, nestedIdentity); } while (nestedParentObjectMapper != null); return nestedIdentity; diff --git a/src/test/java/org/elasticsearch/search/innerhits/InnerHitsTests.java b/src/test/java/org/elasticsearch/search/innerhits/InnerHitsTests.java index 7300331cab265..ed55c4e94f9a9 100644 --- a/src/test/java/org/elasticsearch/search/innerhits/InnerHitsTests.java +++ b/src/test/java/org/elasticsearch/search/innerhits/InnerHitsTests.java @@ -851,13 +851,13 @@ public void testInnerHitsWithObjectFieldThatHasANestedField() throws Exception { assertAcked(prepareCreate("articles") .addMapping("article", jsonBuilder().startObject() .startObject("properties") - .startObject("comments") - .field("type", "object") - .startObject("properties") - .startObject("messages").field("type", "nested").endObject() - .endObject() - .endObject() - .endObject() + .startObject("comments") + .field("type", "object") + .startObject("properties") + .startObject("messages").field("type", "nested").endObject() + .endObject() + .endObject() + .endObject() .endObject() ) ); @@ -865,7 +865,12 @@ public void testInnerHitsWithObjectFieldThatHasANestedField() throws Exception { List requests = new ArrayList<>(); requests.add(client().prepareIndex("articles", "article", "1").setSource(jsonBuilder().startObject() .field("title", "quick brown fox") - .startObject("comments").startObject("messages").field("message", "fox eat quick").endObject().endObject() + .startObject("comments") + .startArray("messages") + .startObject().field("message", "fox eat quick").endObject() + .startObject().field("message", "bear eat quick").endObject() + .endArray() + .endObject() .endObject())); indexRandom(true, requests); @@ -877,11 +882,21 @@ public void testInnerHitsWithObjectFieldThatHasANestedField() throws Exception { assertThat(response.getHits().getAt(0).id(), equalTo("1")); assertThat(response.getHits().getAt(0).getInnerHits().get("comments.messages").getTotalHits(), equalTo(1l)); assertThat(response.getHits().getAt(0).getInnerHits().get("comments.messages").getAt(0).id(), equalTo("1")); - assertThat(response.getHits().getAt(0).getInnerHits().get("comments.messages").getAt(0).getNestedIdentity().getField().string(), equalTo("comments")); + assertThat(response.getHits().getAt(0).getInnerHits().get("comments.messages").getAt(0).getNestedIdentity().getField().string(), equalTo("comments.messages")); assertThat(response.getHits().getAt(0).getInnerHits().get("comments.messages").getAt(0).getNestedIdentity().getOffset(), equalTo(0)); - assertThat(response.getHits().getAt(0).getInnerHits().get("comments.messages").getAt(0).getNestedIdentity().getChild().getField().string(), equalTo("messages")); - assertThat(response.getHits().getAt(0).getInnerHits().get("comments.messages").getAt(0).getNestedIdentity().getChild().getOffset(), equalTo(0)); - assertThat(response.getHits().getAt(0).getInnerHits().get("comments.messages").getAt(0).getNestedIdentity().getChild().getChild(), nullValue()); + assertThat(response.getHits().getAt(0).getInnerHits().get("comments.messages").getAt(0).getNestedIdentity().getChild(), nullValue()); + + response = client().prepareSearch("articles") + .setQuery(nestedQuery("comments.messages", matchQuery("comments.messages.message", "bear")).innerHit(new QueryInnerHitBuilder())) + .get(); + assertNoFailures(response); + assertHitCount(response, 1); + assertThat(response.getHits().getAt(0).id(), equalTo("1")); + assertThat(response.getHits().getAt(0).getInnerHits().get("comments.messages").getTotalHits(), equalTo(1l)); + assertThat(response.getHits().getAt(0).getInnerHits().get("comments.messages").getAt(0).id(), equalTo("1")); + assertThat(response.getHits().getAt(0).getInnerHits().get("comments.messages").getAt(0).getNestedIdentity().getField().string(), equalTo("comments.messages")); + assertThat(response.getHits().getAt(0).getInnerHits().get("comments.messages").getAt(0).getNestedIdentity().getOffset(), equalTo(1)); + assertThat(response.getHits().getAt(0).getInnerHits().get("comments.messages").getAt(0).getNestedIdentity().getChild(), nullValue()); } }