diff --git a/core/src/main/java/org/elasticsearch/action/search/SearchRequestBuilder.java b/core/src/main/java/org/elasticsearch/action/search/SearchRequestBuilder.java index 5c08acb99ea3d..2c30a3f1f43ba 100644 --- a/core/src/main/java/org/elasticsearch/action/search/SearchRequestBuilder.java +++ b/core/src/main/java/org/elasticsearch/action/search/SearchRequestBuilder.java @@ -289,6 +289,11 @@ public SearchRequestBuilder setFetchSource(@Nullable String[] includes, @Nullabl return this; } + public SearchRequestBuilder setFetchMetadata(boolean fetch) { + sourceBuilder().fetchMetadata(fetch); + return this; + } + /** * Adds a docvalue based field to load and return. The field does not have to be stored, * but its recommended to use non analyzed or numeric fields. diff --git a/core/src/main/java/org/elasticsearch/search/SearchService.java b/core/src/main/java/org/elasticsearch/search/SearchService.java index 4d618eb057a6a..5e4544a560975 100644 --- a/core/src/main/java/org/elasticsearch/search/SearchService.java +++ b/core/src/main/java/org/elasticsearch/search/SearchService.java @@ -21,7 +21,6 @@ import com.carrotsearch.hppc.ObjectFloatHashMap; import org.apache.lucene.search.FieldDoc; -import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.TopDocs; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ExceptionsHelper; @@ -813,6 +812,24 @@ private void parseSource(DefaultSearchContext context, SearchSourceBuilder sourc } context.sliceBuilder(source.slice()); } + + if (source.fetchMetadata() != null) { + if (source.fetchMetadata() == false) { + if (context.version()) { + throw new SearchContextException(context, + "`fetch_metadata` is required when version is requested"); + } + if (context.hasFieldNames()) { + throw new SearchContextException(context, + "`fetch_metadata` is required when stored fields are requested"); + } + if (context.sourceRequested() || + (context.hasFetchSourceContext() == false && context.hasScriptFields())) { + throw new SearchContextException(context, "`fetch_metadata` cannot be false if _source is requested"); + } + } + context.fetchMetadata(source.fetchMetadata()); + } } /** diff --git a/core/src/main/java/org/elasticsearch/search/builder/SearchSourceBuilder.java b/core/src/main/java/org/elasticsearch/search/builder/SearchSourceBuilder.java index d31c3d371d64f..c2386444496d6 100644 --- a/core/src/main/java/org/elasticsearch/search/builder/SearchSourceBuilder.java +++ b/core/src/main/java/org/elasticsearch/search/builder/SearchSourceBuilder.java @@ -82,6 +82,7 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ public static final ParseField VERSION_FIELD = new ParseField("version"); public static final ParseField EXPLAIN_FIELD = new ParseField("explain"); public static final ParseField _SOURCE_FIELD = new ParseField("_source"); + public static final ParseField FETCH_METADATA_FIELD = new ParseField("fetch_metadata"); public static final ParseField FIELDS_FIELD = new ParseField("fields"); public static final ParseField STORED_FIELDS_FIELD = new ParseField("stored_fields"); public static final ParseField DOCVALUE_FIELDS_FIELD = new ParseField("docvalue_fields", "fielddata_fields"); @@ -152,6 +153,7 @@ public static HighlightBuilder highlight() { private List docValueFields; private List scriptFields; private FetchSourceContext fetchSourceContext; + private Boolean fetchMetadata; private AggregatorFactories.Builder aggregations; @@ -183,6 +185,7 @@ public SearchSourceBuilder(StreamInput in) throws IOException { aggregations = in.readOptionalWriteable(AggregatorFactories.Builder::new); explain = in.readOptionalBoolean(); fetchSourceContext = in.readOptionalStreamable(FetchSourceContext::new); + fetchMetadata = in.readOptionalBoolean(); docValueFields = (List) in.readGenericValue(); storedFieldNames = (List) in.readGenericValue(); from = in.readVInt(); @@ -243,6 +246,7 @@ public void writeTo(StreamOutput out) throws IOException { out.writeOptionalWriteable(aggregations); out.writeOptionalBoolean(explain); out.writeOptionalStreamable(fetchSourceContext); + out.writeOptionalBoolean(fetchMetadata); out.writeGenericValue(docValueFields); out.writeGenericValue(storedFieldNames); out.writeVInt(from); @@ -705,6 +709,21 @@ public FetchSourceContext fetchSource() { return fetchSourceContext; } + /** + * Indicate if the metadata fields should be fetched + */ + public SearchSourceBuilder fetchMetadata(boolean fetch) { + this.fetchMetadata = fetch; + return this; + } + + /** + * Returns true if the metadata fields should be fetched + */ + public Boolean fetchMetadata() { + return fetchMetadata; + } + /** * Adds a stored field to load and return as part of the * search request. If none are specified, the source of the document will be @@ -911,6 +930,7 @@ private SearchSourceBuilder shallowCopy(QueryBuilder queryBuilder, QueryBuilder rewrittenBuilder.explain = explain; rewrittenBuilder.ext = ext; rewrittenBuilder.fetchSourceContext = fetchSourceContext; + rewrittenBuilder.fetchMetadata = fetchMetadata; rewrittenBuilder.docValueFields = docValueFields; rewrittenBuilder.storedFieldNames = storedFieldNames; rewrittenBuilder.from = from; @@ -972,6 +992,8 @@ public void parseXContent(QueryParseContext context, AggregatorParsers aggParser trackScores = parser.booleanValue(); } else if (context.getParseFieldMatcher().match(currentFieldName, _SOURCE_FIELD)) { fetchSourceContext = FetchSourceContext.parse(context); + } else if (context.getParseFieldMatcher().match(currentFieldName, FETCH_METADATA_FIELD)) { + fetchMetadata = parser.booleanValue(); } else if (context.getParseFieldMatcher().match(currentFieldName, STORED_FIELDS_FIELD)) { storedField(parser.text()); } else if (context.getParseFieldMatcher().match(currentFieldName, SORT_FIELD)) { @@ -1141,6 +1163,10 @@ public void innerToXContent(XContentBuilder builder, Params params) throws IOExc builder.field(_SOURCE_FIELD.getPreferredName(), fetchSourceContext); } + if (fetchMetadata != null) { + builder.field(FETCH_METADATA_FIELD.getPreferredName(), fetchMetadata); + } + if (storedFieldNames != null) { if (storedFieldNames.size() == 1) { builder.field(STORED_FIELDS_FIELD.getPreferredName(), storedFieldNames.get(0)); @@ -1349,7 +1375,7 @@ public boolean equals(Object obj) { @Override public int hashCode() { - return Objects.hash(aggregations, explain, fetchSourceContext, docValueFields, storedFieldNames, from, + return Objects.hash(aggregations, explain, fetchSourceContext, fetchMetadata, docValueFields, storedFieldNames, from, highlightBuilder, indexBoost, minScore, postQueryBuilder, queryBuilder, rescoreBuilders, scriptFields, size, sorts, searchAfterBuilder, sliceBuilder, stats, suggestBuilder, terminateAfter, timeout, trackScores, version, profile); } @@ -1366,6 +1392,7 @@ public boolean equals(Object obj) { return Objects.equals(aggregations, other.aggregations) && Objects.equals(explain, other.explain) && Objects.equals(fetchSourceContext, other.fetchSourceContext) + && Objects.equals(fetchMetadata, other.fetchMetadata) && Objects.equals(docValueFields, other.docValueFields) && Objects.equals(storedFieldNames, other.storedFieldNames) && Objects.equals(from, other.from) diff --git a/core/src/main/java/org/elasticsearch/search/fetch/FetchPhase.java b/core/src/main/java/org/elasticsearch/search/fetch/FetchPhase.java index beb64120788c7..0875c5edc9778 100644 --- a/core/src/main/java/org/elasticsearch/search/fetch/FetchPhase.java +++ b/core/src/main/java/org/elasticsearch/search/fetch/FetchPhase.java @@ -97,12 +97,21 @@ public void execute(SearchContext context) { List fieldNamePatterns = null; if (!context.hasFieldNames()) { // no fields specified, default to return source if no explicit indication - if (!context.hasScriptFields() && !context.hasFetchSourceContext()) { + if (!context.hasScriptFields() && !context.hasFetchSourceContext() && context.fetchMetadata()) { context.fetchSourceContext(new FetchSourceContext(true)); } - fieldsVisitor = new FieldsVisitor(context.sourceRequested()); + if (context.fetchMetadata() == false) { + assert context.sourceRequested() == false; + fieldsVisitor = null; + } else { + fieldsVisitor = new FieldsVisitor(context.sourceRequested()); + } } else if (context.fieldNames().isEmpty()) { - fieldsVisitor = new FieldsVisitor(context.sourceRequested()); + if (context.fetchMetadata() == false && context.sourceRequested() == false) { + fieldsVisitor = null; + } else { + fieldsVisitor = new FieldsVisitor(context.sourceRequested()); + } } else { for (String fieldName : context.fieldNames()) { if (fieldName.equals(SourceFieldMapper.NAME)) { @@ -182,6 +191,9 @@ private int findRootDocumentIfNested(SearchContext context, LeafReaderContext su } private InternalSearchHit createSearchHit(SearchContext context, FieldsVisitor fieldsVisitor, int docId, int subDocId, LeafReaderContext subReaderContext) { + if (fieldsVisitor == null) { + return new InternalSearchHit(docId, null, null, null); + } loadStoredFields(context, subReaderContext, fieldsVisitor, subDocId); fieldsVisitor.postProcess(context.mapperService()); @@ -193,14 +205,18 @@ private InternalSearchHit createSearchHit(SearchContext context, FieldsVisitor f } } - DocumentMapper documentMapper = context.mapperService().documentMapper(fieldsVisitor.uid().type()); - Text typeText; - if (documentMapper == null) { - typeText = new Text(fieldsVisitor.uid().type()); - } else { - typeText = documentMapper.typeText(); + Text typeText = null; + String id = null; + if (context.fetchMetadata()) { + DocumentMapper documentMapper = context.mapperService().documentMapper(fieldsVisitor.uid().type()); + if (documentMapper == null) { + typeText = new Text(fieldsVisitor.uid().type()); + } else { + typeText = documentMapper.typeText(); + } + id = fieldsVisitor.uid().id(); } - InternalSearchHit searchHit = new InternalSearchHit(docId, fieldsVisitor.uid().id(), typeText, searchFields); + InternalSearchHit searchHit = new InternalSearchHit(docId, id, typeText, searchFields); // Set _source if requested. SourceLookup sourceLookup = context.lookup().source(); sourceLookup.setSegmentAndDocument(subReaderContext, subDocId); diff --git a/core/src/main/java/org/elasticsearch/search/fetch/parent/ParentFieldSubFetchPhase.java b/core/src/main/java/org/elasticsearch/search/fetch/parent/ParentFieldSubFetchPhase.java index 6ace9a86a3e5f..c1a7fd6cf6b33 100644 --- a/core/src/main/java/org/elasticsearch/search/fetch/parent/ParentFieldSubFetchPhase.java +++ b/core/src/main/java/org/elasticsearch/search/fetch/parent/ParentFieldSubFetchPhase.java @@ -38,6 +38,9 @@ public final class ParentFieldSubFetchPhase implements FetchSubPhase { @Override public void hitExecute(SearchContext context, HitContext hitContext) { + if (context.fetchMetadata() == false) { + return ; + } ParentFieldMapper parentFieldMapper = context.mapperService().documentMapper(hitContext.hit().type()).parentFieldMapper(); if (parentFieldMapper.active() == false) { return; diff --git a/core/src/main/java/org/elasticsearch/search/internal/DefaultSearchContext.java b/core/src/main/java/org/elasticsearch/search/internal/DefaultSearchContext.java index ffc6e4938c878..1ff3cee4b9666 100644 --- a/core/src/main/java/org/elasticsearch/search/internal/DefaultSearchContext.java +++ b/core/src/main/java/org/elasticsearch/search/internal/DefaultSearchContext.java @@ -109,6 +109,7 @@ public class DefaultSearchContext extends SearchContext { private List fieldNames; private ScriptFieldsContext scriptFields; private FetchSourceContext fetchSourceContext; + private boolean fetchMetadata = true; private int from = -1; private int size = -1; private SortAndFormats sort; @@ -469,6 +470,18 @@ public SearchContext fetchSourceContext(FetchSourceContext fetchSourceContext) { return this; } + @Override + public boolean fetchMetadata() { + return fetchMetadata; + } + + @Override + public SearchContext fetchMetadata(boolean fetch) { + this.fetchMetadata = fetch; + return this; + } + + @Override public ContextIndexSearcher searcher() { return this.searcher; diff --git a/core/src/main/java/org/elasticsearch/search/internal/FilteredSearchContext.java b/core/src/main/java/org/elasticsearch/search/internal/FilteredSearchContext.java index 6c646a62b6b11..f2cbda57fb293 100644 --- a/core/src/main/java/org/elasticsearch/search/internal/FilteredSearchContext.java +++ b/core/src/main/java/org/elasticsearch/search/internal/FilteredSearchContext.java @@ -219,6 +219,16 @@ public SearchContext fetchSourceContext(FetchSourceContext fetchSourceContext) { return in.fetchSourceContext(fetchSourceContext); } + @Override + public boolean fetchMetadata() { + return in.fetchMetadata(); + } + + @Override + public SearchContext fetchMetadata(boolean fetch) { + return in.fetchMetadata(fetch); + } + @Override public ContextIndexSearcher searcher() { return in.searcher(); diff --git a/core/src/main/java/org/elasticsearch/search/internal/InternalSearchHit.java b/core/src/main/java/org/elasticsearch/search/internal/InternalSearchHit.java index e1d46dd5fd287..3149d728b3e53 100644 --- a/core/src/main/java/org/elasticsearch/search/internal/InternalSearchHit.java +++ b/core/src/main/java/org/elasticsearch/search/internal/InternalSearchHit.java @@ -100,16 +100,16 @@ private InternalSearchHit() { } - public InternalSearchHit(int docId, String id, Text type, Map fields) { + public InternalSearchHit(int docId, @Nullable String id, @Nullable Text type, @Nullable Map fields) { this.docId = docId; - this.id = new Text(id); + this.id = id != null ? new Text(id) : null; this.type = type; this.fields = fields; } public InternalSearchHit(int nestedTopDocId, String id, Text type, InternalNestedIdentity nestedIdentity, Map fields) { this.docId = nestedTopDocId; - this.id = new Text(id); + this.id = id != null ? new Text(id) : null; this.type = type; this.nestedIdentity = nestedIdentity; this.fields = fields; @@ -168,7 +168,7 @@ public String getIndex() { @Override public String id() { - return id.string(); + return id != null ? id.string() : null; } @Override @@ -178,7 +178,7 @@ public String getId() { @Override public String type() { - return type.string(); + return type != null ? type.string() : null; } @Override @@ -444,8 +444,12 @@ public XContentBuilder toInnerXContent(XContentBuilder builder, Params params) t if (shard != null) { builder.field(Fields._INDEX, shard.indexText()); } - builder.field(Fields._TYPE, type); - builder.field(Fields._ID, id); + if (type != null) { + builder.field(Fields._TYPE, type); + } + if (id != null) { + builder.field(Fields._ID, id); + } } if (version != -1) { builder.field(Fields._VERSION, version); @@ -555,8 +559,8 @@ public void readFrom(StreamInput in) throws IOException { public void readFrom(StreamInput in, InternalSearchHits.StreamContext context) throws IOException { score = in.readFloat(); - id = in.readText(); - type = in.readText(); + id = in.readOptionalText(); + type = in.readOptionalText(); nestedIdentity = in.readOptionalStreamable(InternalNestedIdentity::new); version = in.readLong(); source = in.readBytesReference(); @@ -664,8 +668,8 @@ public void writeTo(StreamOutput out) throws IOException { public void writeTo(StreamOutput out, InternalSearchHits.StreamContext context) throws IOException { out.writeFloat(score); - out.writeText(id); - out.writeText(type); + out.writeOptionalText(id); + out.writeOptionalText(type); out.writeOptionalStreamable(nestedIdentity); out.writeLong(version); out.writeBytesReference(source); diff --git a/core/src/main/java/org/elasticsearch/search/internal/SearchContext.java b/core/src/main/java/org/elasticsearch/search/internal/SearchContext.java index 3112212dc51c5..e5ecc1ec24b28 100644 --- a/core/src/main/java/org/elasticsearch/search/internal/SearchContext.java +++ b/core/src/main/java/org/elasticsearch/search/internal/SearchContext.java @@ -64,7 +64,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicBoolean; public abstract class SearchContext implements Releasable { @@ -200,6 +199,10 @@ public InnerHitsContext innerHits() { public abstract SearchContext fetchSourceContext(FetchSourceContext fetchSourceContext); + public abstract boolean fetchMetadata(); + + public abstract SearchContext fetchMetadata(boolean fetch); + public abstract ContextIndexSearcher searcher(); public abstract IndexShard indexShard(); diff --git a/core/src/test/java/org/elasticsearch/search/builder/SearchSourceBuilderTests.java b/core/src/test/java/org/elasticsearch/search/builder/SearchSourceBuilderTests.java index 833e14fe21c1b..5ec601635b906 100644 --- a/core/src/test/java/org/elasticsearch/search/builder/SearchSourceBuilderTests.java +++ b/core/src/test/java/org/elasticsearch/search/builder/SearchSourceBuilderTests.java @@ -408,6 +408,10 @@ protected final SearchSourceBuilder createSearchSourceBuilder() throws IOExcepti builder.slice(new SliceBuilder(field, id, max)); } } + + if (randomBoolean()) { + builder.fetchMetadata(randomBoolean()); + } return builder; } @@ -550,14 +554,14 @@ public void testParseSort() throws IOException { public void testAggsParsing() throws IOException { { - String restContent = "{\n" + " " + - "\"aggs\": {" + - " \"test_agg\": {\n" + - " " + "\"terms\" : {\n" + - " \"field\": \"foo\"\n" + - " }\n" + - " }\n" + - " }\n" + + String restContent = "{\n" + " " + + "\"aggs\": {" + + " \"test_agg\": {\n" + + " " + "\"terms\" : {\n" + + " \"field\": \"foo\"\n" + + " }\n" + + " }\n" + + " }\n" + "}\n"; try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) { SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.fromXContent(createParseContext(parser), aggParsers, @@ -566,14 +570,14 @@ public void testAggsParsing() throws IOException { } } { - String restContent = "{\n" + - " \"aggregations\": {" + - " \"test_agg\": {\n" + - " \"terms\" : {\n" + - " \"field\": \"foo\"\n" + - " }\n" + - " }\n" + - " }\n" + + String restContent = "{\n" + + " \"aggregations\": {" + + " \"test_agg\": {\n" + + " \"terms\" : {\n" + + " \"field\": \"foo\"\n" + + " }\n" + + " }\n" + + " }\n" + "}\n"; try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) { SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.fromXContent(createParseContext(parser), aggParsers, diff --git a/core/src/test/java/org/elasticsearch/search/source/MetadatFetchingIT.java b/core/src/test/java/org/elasticsearch/search/source/MetadatFetchingIT.java new file mode 100644 index 0000000000000..dc94b96289374 --- /dev/null +++ b/core/src/test/java/org/elasticsearch/search/source/MetadatFetchingIT.java @@ -0,0 +1,119 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.elasticsearch.search.source; + +import org.elasticsearch.ExceptionsHelper; +import org.elasticsearch.action.search.SearchPhaseExecutionException; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.search.SearchContextException; +import org.elasticsearch.test.ESIntegTestCase; + +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.nullValue; + +public class MetadatFetchingIT extends ESIntegTestCase { + public void testSimple() { + assertAcked(prepareCreate("test")); + ensureGreen(); + + client().prepareIndex("test", "type1", "1").setSource("field", "value").execute().actionGet(); + refresh(); + + SearchResponse response = client() + .prepareSearch("test") + .setFetchMetadata(false) + .setFetchSource(false) + .get(); + assertThat(response.getHits().getAt(0).getId(), nullValue()); + assertThat(response.getHits().getAt(0).getType(), nullValue()); + assertThat(response.getHits().getAt(0).sourceAsString(), nullValue()); + + response = client() + .prepareSearch("test") + .setFetchMetadata(false) + .get(); + assertThat(response.getHits().getAt(0).getId(), nullValue()); + assertThat(response.getHits().getAt(0).getType(), nullValue()); + assertThat(response.getHits().getAt(0).sourceAsString(), nullValue()); + } + + public void testWithRouting() { + assertAcked(prepareCreate("test")); + ensureGreen(); + + client().prepareIndex("test", "type1", "1").setSource("field", "value").setRouting("toto").execute().actionGet(); + refresh(); + + SearchResponse response = client() + .prepareSearch("test") + .setFetchMetadata(false) + .setFetchSource(false) + .get(); + assertThat(response.getHits().getAt(0).getId(), nullValue()); + assertThat(response.getHits().getAt(0).getType(), nullValue()); + assertThat(response.getHits().getAt(0).field("_routing"), nullValue()); + assertThat(response.getHits().getAt(0).sourceAsString(), nullValue()); + + response = client() + .prepareSearch("test") + .setFetchMetadata(false) + .get(); + assertThat(response.getHits().getAt(0).getId(), nullValue()); + assertThat(response.getHits().getAt(0).getType(), nullValue()); + assertThat(response.getHits().getAt(0).sourceAsString(), nullValue()); + } + + public void testInvalid() { + assertAcked(prepareCreate("test")); + ensureGreen(); + + index("test", "type1", "1", "field", "value"); + refresh(); + + { + SearchPhaseExecutionException exc = expectThrows(SearchPhaseExecutionException.class, + () -> client().prepareSearch("test").setFetchSource(true).setFetchMetadata(false).get()); + Throwable rootCause = ExceptionsHelper.unwrap(exc, SearchContextException.class); + assertNotNull(rootCause); + assertThat(rootCause.getClass(), equalTo(SearchContextException.class)); + assertThat(rootCause.getMessage(), + equalTo("`fetch_metadata` cannot be false if _source is requested")); + } + { + SearchPhaseExecutionException exc = expectThrows(SearchPhaseExecutionException.class, + () -> client().prepareSearch("test").setFetchMetadata(false).setVersion(true).get()); + Throwable rootCause = ExceptionsHelper.unwrap(exc, SearchContextException.class); + assertNotNull(rootCause); + assertThat(rootCause.getClass(), equalTo(SearchContextException.class)); + assertThat(rootCause.getMessage(), + equalTo("`fetch_metadata` is required when version is requested")); + } + + { + SearchPhaseExecutionException exc = expectThrows(SearchPhaseExecutionException.class, + () -> client().prepareSearch("test").setFetchMetadata(false).storedFields("field").get()); + Throwable rootCause = ExceptionsHelper.unwrap(exc, SearchContextException.class); + assertNotNull(rootCause); + assertThat(rootCause.getClass(), equalTo(SearchContextException.class)); + assertThat(rootCause.getMessage(), + equalTo("`fetch_metadata` is required when stored fields are requested")); + } + } +} diff --git a/docs/reference/search/request/fetch-metadata.asciidoc b/docs/reference/search/request/fetch-metadata.asciidoc new file mode 100644 index 0000000000000..84836ef9ea220 --- /dev/null +++ b/docs/reference/search/request/fetch-metadata.asciidoc @@ -0,0 +1,22 @@ +[[search-request-fetch-metadata]] +=== Fetch metadata + +Allows to disable the retrieval of the metadata fields (`_source`, `_id`, `_type`, `routing`, `parent`). + +By default search operations return the metadata fields of each search result. + +You can turn off the retrieval by using the `fetch_metadata` parameter: + +[source,js] +-------------------------------------------------- +GET /_search +{ + "fetch_metadata": false + "query" : { + "term" : { "user" : "kimchy" } + } +} +-------------------------------------------------- +// CONSOLE + +NOTE: <>, <> and <> parameters cannot be used if `fetch_metadata` is disabled. diff --git a/test/framework/src/main/java/org/elasticsearch/test/TestSearchContext.java b/test/framework/src/main/java/org/elasticsearch/test/TestSearchContext.java index 97240bd9e5e77..5b54f6c4499e7 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/TestSearchContext.java +++ b/test/framework/src/main/java/org/elasticsearch/test/TestSearchContext.java @@ -18,10 +18,6 @@ */ package org.elasticsearch.test; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import org.apache.lucene.search.Collector; import org.apache.lucene.search.FieldDoc; import org.apache.lucene.search.Query; @@ -65,6 +61,10 @@ import org.elasticsearch.search.suggest.SuggestionSearchContext; import org.elasticsearch.threadpool.ThreadPool; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + public class TestSearchContext extends SearchContext { final BigArrays bigArrays; @@ -261,6 +261,16 @@ public SearchContext fetchSourceContext(FetchSourceContext fetchSourceContext) { return null; } + @Override + public boolean fetchMetadata() { + return false; + } + + @Override + public SearchContext fetchMetadata(boolean fetch) { + return null; + } + @Override public ContextIndexSearcher searcher() { return searcher;