Moved the check to fetch phase. This basically means that we throw

a better error message instead of an AOBE and not adding more restrictions.
This commit is contained in:
Martijn van Groningen 2017-07-31 14:47:30 +02:00
parent d05aee7eda
commit f782f618cc
No known key found for this signature in database
GPG Key ID: AB236F4FCF2AF12A
3 changed files with 35 additions and 30 deletions

View File

@ -353,11 +353,6 @@ public class NestedQueryBuilder extends AbstractQueryBuilder<NestedQueryBuilder>
name, parentSearchContext, parentObjectMapper, nestedObjectMapper
);
setupInnerHitsContext(queryShardContext, nestedInnerHits);
if ((nestedInnerHits.hasFetchSourceContext() == false || nestedInnerHits.sourceRequested()) &&
nestedObjectMapper.parentObjectMapperAreNested(parentSearchContext.mapperService()) == false) {
throw new IllegalArgumentException("Cannot execute inner hits. One or more parent object fields of nested field [" +
nestedObjectMapper.name() + "] are not nested. All parent fields need to be nested fields too");
}
queryShardContext.nestedScope().previousLevel();
innerHitsContext.addInnerHitDefinition(nestedInnerHits);
}

View File

@ -263,18 +263,23 @@ public class FetchPhase implements SearchPhase {
String nestedPath = nested.getField().string();
current.put(nestedPath, new HashMap<>());
Object extractedValue = XContentMapValues.extractValue(nestedPath, sourceAsMap);
List<Map<String, Object>> nestedParsedSource;
List<?> nestedParsedSource;
if (extractedValue instanceof List) {
// nested field has an array value in the _source
nestedParsedSource = (List<Map<String, Object>>) extractedValue;
nestedParsedSource = (List<?>) extractedValue;
} else if (extractedValue instanceof Map) {
// nested field has an object value in the _source. This just means the nested field has just one inner object,
// which is valid, but uncommon.
nestedParsedSource = Collections.singletonList((Map<String, Object>) extractedValue);
nestedParsedSource = Collections.singletonList(extractedValue);
} else {
throw new IllegalStateException("extracted source isn't an object or an array");
}
sourceAsMap = nestedParsedSource.get(nested.getOffset());
if ((nestedParsedSource.get(0) instanceof Map) == false &&
nestedObjectMapper.parentObjectMapperAreNested(context.mapperService()) == false) {
throw new IllegalArgumentException("Cannot execute inner hits. One or more parent object fields of nested field [" +
nestedObjectMapper.name() + "] are not nested. All parent fields need to be nested fields too");
}
sourceAsMap = (Map<String, Object>) nestedParsedSource.get(nested.getOffset());
if (nested.getChild() == null) {
current.put(nestedPath, sourceAsMap);
} else {

View File

@ -402,33 +402,34 @@ public class InnerHitsIT extends ESIntegTestCase {
List<IndexRequestBuilder> requests = new ArrayList<>();
requests.add(client().prepareIndex("articles", "article", "1").setSource(jsonBuilder().startObject()
.field("title", "quick brown fox")
.startObject("comments")
.startArray("messages")
.startObject().field("message", "fox eat quick").endObject()
.startObject().field("message", "bear eat quick").endObject()
.startArray("comments")
.startObject()
.startArray("messages")
.startObject().field("message", "fox eat quick").endObject()
.startObject().field("message", "bear eat quick").endObject()
.endArray()
.endObject()
.startObject()
.startArray("messages")
.startObject().field("message", "no fox").endObject()
.endArray()
.endObject()
.endArray()
.endObject()
.endObject()));
indexRandom(true, requests);
SearchPhaseExecutionException e = expectThrows(
SearchPhaseExecutionException.class,
() -> client().prepareSearch("articles").setQuery(nestedQuery("comments.messages",
matchQuery("comments.messages.message", "fox"), ScoreMode.Avg).innerHit(new InnerHitBuilder())).get()
);
SearchResponse response = client().prepareSearch("articles").setQuery(nestedQuery("comments.messages",
matchQuery("comments.messages.message", "fox"), ScoreMode.Avg).innerHit(new InnerHitBuilder())).get();
assertEquals("Cannot execute inner hits. One or more parent object fields of nested field [comments.messages] are " +
"not nested. All parent fields need to be nested fields too", e.shardFailures()[0].getCause().getMessage());
"not nested. All parent fields need to be nested fields too", response.getShardFailures()[0].getCause().getMessage());
e = expectThrows(
SearchPhaseExecutionException.class,
() -> client().prepareSearch("articles").setQuery(nestedQuery("comments.messages",
matchQuery("comments.messages.message", "fox"), ScoreMode.Avg).innerHit(new InnerHitBuilder()
.setFetchSourceContext(new FetchSourceContext(true)))).get()
);
response = client().prepareSearch("articles").setQuery(nestedQuery("comments.messages",
matchQuery("comments.messages.message", "fox"), ScoreMode.Avg).innerHit(new InnerHitBuilder()
.setFetchSourceContext(new FetchSourceContext(true)))).get();
assertEquals("Cannot execute inner hits. One or more parent object fields of nested field [comments.messages] are " +
"not nested. All parent fields need to be nested fields too", e.shardFailures()[0].getCause().getMessage());
"not nested. All parent fields need to be nested fields too", response.getShardFailures()[0].getCause().getMessage());
SearchResponse response = client().prepareSearch("articles")
response = client().prepareSearch("articles")
.setQuery(nestedQuery("comments.messages", matchQuery("comments.messages.message", "fox"), ScoreMode.Avg)
.innerHit(new InnerHitBuilder().setFetchSourceContext(new FetchSourceContext(false)))).get();
assertNoFailures(response);
@ -436,11 +437,15 @@ public class InnerHitsIT extends ESIntegTestCase {
SearchHit hit = response.getHits().getAt(0);
assertThat(hit.getId(), equalTo("1"));
SearchHits messages = hit.getInnerHits().get("comments.messages");
assertThat(messages.getTotalHits(), equalTo(1L));
assertThat(messages.getTotalHits(), equalTo(2L));
assertThat(messages.getAt(0).getId(), equalTo("1"));
assertThat(messages.getAt(0).getNestedIdentity().getField().string(), equalTo("comments.messages"));
assertThat(messages.getAt(0).getNestedIdentity().getOffset(), equalTo(0));
assertThat(messages.getAt(0).getNestedIdentity().getOffset(), equalTo(2));
assertThat(messages.getAt(0).getNestedIdentity().getChild(), nullValue());
assertThat(messages.getAt(1).getId(), equalTo("1"));
assertThat(messages.getAt(1).getNestedIdentity().getField().string(), equalTo("comments.messages"));
assertThat(messages.getAt(1).getNestedIdentity().getOffset(), equalTo(0));
assertThat(messages.getAt(1).getNestedIdentity().getChild(), nullValue());
response = client().prepareSearch("articles")
.setQuery(nestedQuery("comments.messages", matchQuery("comments.messages.message", "bear"), ScoreMode.Avg)