inner_hits: Return an empty _source for nested inner hit when filtering on a field that doesn't exist.
Before this change the search request would fail with an error indicating that it couldn't detect xcontent type based on the string: `null`
This commit is contained in:
parent
4ab638b71d
commit
3f98b85489
|
@ -20,21 +20,16 @@
|
||||||
package org.elasticsearch.search.fetch.subphase;
|
package org.elasticsearch.search.fetch.subphase;
|
||||||
|
|
||||||
import org.elasticsearch.ElasticsearchException;
|
import org.elasticsearch.ElasticsearchException;
|
||||||
import org.elasticsearch.common.bytes.BytesReference;
|
|
||||||
import org.elasticsearch.common.io.stream.BytesStreamOutput;
|
import org.elasticsearch.common.io.stream.BytesStreamOutput;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.common.xcontent.XContentType;
|
|
||||||
import org.elasticsearch.search.SearchHit;
|
import org.elasticsearch.search.SearchHit;
|
||||||
import org.elasticsearch.search.fetch.FetchSubPhase;
|
import org.elasticsearch.search.fetch.FetchSubPhase;
|
||||||
import org.elasticsearch.search.internal.SearchContext;
|
import org.elasticsearch.search.internal.SearchContext;
|
||||||
import org.elasticsearch.search.lookup.SourceLookup;
|
import org.elasticsearch.search.lookup.SourceLookup;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.UncheckedIOException;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.elasticsearch.common.xcontent.XContentFactory.contentBuilder;
|
|
||||||
|
|
||||||
public final class FetchSourceSubPhase implements FetchSubPhase {
|
public final class FetchSourceSubPhase implements FetchSubPhase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -65,7 +60,17 @@ public final class FetchSourceSubPhase implements FetchSubPhase {
|
||||||
final int initialCapacity = nestedHit ? 1024 : Math.min(1024, source.internalSourceRef().length());
|
final int initialCapacity = nestedHit ? 1024 : Math.min(1024, source.internalSourceRef().length());
|
||||||
BytesStreamOutput streamOutput = new BytesStreamOutput(initialCapacity);
|
BytesStreamOutput streamOutput = new BytesStreamOutput(initialCapacity);
|
||||||
XContentBuilder builder = new XContentBuilder(source.sourceContentType().xContent(), streamOutput);
|
XContentBuilder builder = new XContentBuilder(source.sourceContentType().xContent(), streamOutput);
|
||||||
builder.value(value);
|
if (value != null) {
|
||||||
|
builder.value(value);
|
||||||
|
} else {
|
||||||
|
// This happens if the source filtering could not find the specified in the _source.
|
||||||
|
// Just doing `builder.value(null)` is valid, but the xcontent validation can't detect what format
|
||||||
|
// it is. In certain cases, for example response serialization we fail if no xcontent type can't be
|
||||||
|
// detected. So instead we just return an empty top level object. Also this is in inline with what was
|
||||||
|
// being return in this situation in 5.x and earlier.
|
||||||
|
builder.startObject();
|
||||||
|
builder.endObject();
|
||||||
|
}
|
||||||
hitContext.hit().sourceRef(builder.bytes());
|
hitContext.hit().sourceRef(builder.bytes());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new ElasticsearchException("Error filtering source", e);
|
throw new ElasticsearchException("Error filtering source", e);
|
||||||
|
|
|
@ -56,7 +56,6 @@ import java.util.function.Function;
|
||||||
|
|
||||||
import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE;
|
import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE;
|
||||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||||
import static org.elasticsearch.common.xcontent.support.XContentMapValues.extractValue;
|
|
||||||
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
|
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
|
||||||
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
|
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
|
||||||
import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
|
import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
|
||||||
|
@ -635,6 +634,18 @@ public class InnerHitsIT extends ESIntegTestCase {
|
||||||
assertThat(response.getHits().getAt(0).getInnerHits().get("comments").getAt(0).getSourceAsMap().size(), equalTo(2));
|
assertThat(response.getHits().getAt(0).getInnerHits().get("comments").getAt(0).getSourceAsMap().size(), equalTo(2));
|
||||||
assertThat(response.getHits().getAt(0).getInnerHits().get("comments").getAt(1).getSourceAsMap().get("message"),
|
assertThat(response.getHits().getAt(0).getInnerHits().get("comments").getAt(1).getSourceAsMap().get("message"),
|
||||||
equalTo("fox ate rabbit x y z"));
|
equalTo("fox ate rabbit x y z"));
|
||||||
|
|
||||||
|
// Source filter on a field that does not exist inside the nested document and just check that we do not fail and
|
||||||
|
// return an empty _source:
|
||||||
|
response = client().prepareSearch()
|
||||||
|
.setQuery(nestedQuery("comments", matchQuery("comments.message", "away"), ScoreMode.None)
|
||||||
|
.innerHit(new InnerHitBuilder().setFetchSourceContext(new FetchSourceContext(true,
|
||||||
|
new String[]{"comments.missing_field"}, null))))
|
||||||
|
.get();
|
||||||
|
assertNoFailures(response);
|
||||||
|
assertHitCount(response, 1);
|
||||||
|
assertThat(response.getHits().getAt(0).getInnerHits().get("comments").getTotalHits(), equalTo(1L));
|
||||||
|
assertThat(response.getHits().getAt(0).getInnerHits().get("comments").getAt(0).getSourceAsMap().size(), equalTo(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testInnerHitsWithIgnoreUnmapped() throws Exception {
|
public void testInnerHitsWithIgnoreUnmapped() throws Exception {
|
||||||
|
|
Loading…
Reference in New Issue