inner hits: Don't fail if an object is specified as a nested value instead of an array.
Closes #9723
This commit is contained in:
parent
4859ce5d79
commit
b2b7506ace
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.elasticsearch.search.fetch;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.index.ReaderUtil;
|
||||
|
@ -27,6 +28,7 @@ import org.apache.lucene.search.Filter;
|
|||
import org.apache.lucene.util.BitDocIdSet;
|
||||
import org.apache.lucene.util.BitSet;
|
||||
import org.elasticsearch.ElasticsearchIllegalArgumentException;
|
||||
import org.elasticsearch.ElasticsearchIllegalStateException;
|
||||
import org.elasticsearch.ExceptionsHelper;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.collect.Tuple;
|
||||
|
@ -293,7 +295,16 @@ public class FetchPhase implements SearchPhase {
|
|||
List<Map<String, Object>> nestedParsedSource;
|
||||
SearchHit.NestedIdentity nested = nestedIdentity;
|
||||
do {
|
||||
nestedParsedSource = (List<Map<String, Object>>) XContentMapValues.extractValue(nested.getField().string(), sourceAsMap);
|
||||
Object extractedValue = XContentMapValues.extractValue(nested.getField().string(), sourceAsMap);
|
||||
if (extractedValue instanceof List) {
|
||||
// nested field has an array value in the _source
|
||||
nestedParsedSource = (List<Map<String, Object>>) 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 = ImmutableList.of((Map < String, Object >) extractedValue);
|
||||
} else {
|
||||
throw new ElasticsearchIllegalStateException("extracted source isn't an object or an array");
|
||||
}
|
||||
sourceAsMap = nestedParsedSource.get(nested.getOffset());
|
||||
nested = nested.getChild();
|
||||
} while (nested != null);
|
||||
|
|
|
@ -645,4 +645,29 @@ public class InnerHitsTests extends ElasticsearchIntegrationTest {
|
|||
assertThat(innerHits.getAt(0).getNestedIdentity().getChild().getOffset(), equalTo(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
// https://github.com/elasticsearch/elasticsearch/issues/9723
|
||||
public void testNestedDefinedAsObject() throws Exception {
|
||||
assertAcked(prepareCreate("articles").addMapping("article", "comments", "type=nested", "title", "type=string"));
|
||||
|
||||
List<IndexRequestBuilder> requests = new ArrayList<>();
|
||||
requests.add(client().prepareIndex("articles", "article", "1").setSource(jsonBuilder().startObject()
|
||||
.field("title", "quick brown fox")
|
||||
.startObject("comments").field("message", "fox eat quick").endObject()
|
||||
.endObject()));
|
||||
indexRandom(true, requests);
|
||||
|
||||
SearchResponse response = client().prepareSearch("articles")
|
||||
.setQuery(nestedQuery("comments", matchQuery("comments.message", "fox")).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").getTotalHits(), equalTo(1l));
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().get("comments").getAt(0).id(), equalTo("1"));
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().get("comments").getAt(0).getNestedIdentity().getField().string(), equalTo("comments"));
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().get("comments").getAt(0).getNestedIdentity().getOffset(), equalTo(0));
|
||||
assertThat(response.getHits().getAt(0).getInnerHits().get("comments").getAt(0).getNestedIdentity().getChild(), nullValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue