Skip to content

Commit 50b47aa

Browse files
authored
Merge pull request #20026 from jimferenczi/disable_stored_fields
Add the ability to disable the retrieval of the stored fields entirely
2 parents acbece5 + 4682fc3 commit 50b47aa

File tree

31 files changed

+764
-329
lines changed

31 files changed

+764
-329
lines changed

core/src/main/java/org/elasticsearch/action/search/SearchRequestBuilder.java

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -249,14 +249,6 @@ public SearchRequestBuilder setStats(List<String> statsGroups) {
249249
return this;
250250
}
251251

252-
/**
253-
* Sets no fields to be loaded, resulting in only id and type to be returned per field.
254-
*/
255-
public SearchRequestBuilder setNoStoredFields() {
256-
sourceBuilder().noStoredFields();
257-
return this;
258-
}
259-
260252
/**
261253
* Indicates whether the response should contain the stored _source for every hit
262254
*/
@@ -302,7 +294,6 @@ public SearchRequestBuilder addDocValueField(String name) {
302294

303295
/**
304296
* Adds a stored field to load and return (note, it must be stored) as part of the search request.
305-
* If none are specified, the source of the document will be return.
306297
*/
307298
public SearchRequestBuilder addStoredField(String field) {
308299
sourceBuilder().storedField(field);
@@ -380,9 +371,8 @@ public SearchRequestBuilder setTrackScores(boolean trackScores) {
380371
}
381372

382373
/**
383-
* Sets the stored fields to load and return as part of the search request. If none
384-
* are specified, the source of the document will be returned.
385-
*
374+
* Adds stored fields to load and return (note, it must be stored) as part of the search request.
375+
* To disable the stored fields entirely (source and metadata fields) use {@code storedField("_none_")}.
386376
* @deprecated Use {@link SearchRequestBuilder#storedFields(String...)} instead.
387377
*/
388378
@Deprecated
@@ -392,8 +382,8 @@ public SearchRequestBuilder fields(String... fields) {
392382
}
393383

394384
/**
395-
* Sets the fields to load and return as part of the search request. If none
396-
* are specified, the source of the document will be returned.
385+
* Adds stored fields to load and return (note, it must be stored) as part of the search request.
386+
* To disable the stored fields entirely (source and metadata fields) use {@code storedField("_none_")}.
397387
*/
398388
public SearchRequestBuilder storedFields(String... fields) {
399389
sourceBuilder().storedFields(Arrays.asList(fields));

core/src/main/java/org/elasticsearch/index/query/InnerHitBuilder.java

Lines changed: 30 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.elasticsearch.script.SearchScript;
3535
import org.elasticsearch.search.builder.SearchSourceBuilder;
3636
import org.elasticsearch.search.builder.SearchSourceBuilder.ScriptField;
37+
import org.elasticsearch.search.fetch.StoredFieldsContext;
3738
import org.elasticsearch.search.fetch.subphase.DocValueFieldsContext;
3839
import org.elasticsearch.search.fetch.subphase.DocValueFieldsFetchSubPhase;
3940
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
@@ -137,7 +138,7 @@ public final class InnerHitBuilder extends ToXContentToBytes implements Writeabl
137138
private boolean version;
138139
private boolean trackScores;
139140

140-
private List<String> storedFieldNames;
141+
private StoredFieldsContext storedFieldsContext;
141142
private QueryBuilder query = DEFAULT_INNER_HIT_QUERY;
142143
private List<SortBuilder<?>> sorts;
143144
private List<String> docValueFields;
@@ -156,14 +157,14 @@ private InnerHitBuilder(InnerHitBuilder other) {
156157
explain = other.explain;
157158
version = other.version;
158159
trackScores = other.trackScores;
159-
if (other.storedFieldNames != null) {
160-
storedFieldNames = new ArrayList<>(other.storedFieldNames);
160+
if (other.storedFieldsContext != null) {
161+
storedFieldsContext = new StoredFieldsContext(other.storedFieldsContext);
161162
}
162163
if (other.docValueFields != null) {
163-
docValueFields = new ArrayList<>(other.docValueFields);
164+
docValueFields = new ArrayList<> (other.docValueFields);
164165
}
165166
if (other.scriptFields != null) {
166-
scriptFields = new HashSet<>(other.scriptFields);
167+
scriptFields = new HashSet<> (other.scriptFields);
167168
}
168169
if (other.fetchSourceContext != null) {
169170
fetchSourceContext = new FetchSourceContext(
@@ -210,7 +211,7 @@ public InnerHitBuilder(StreamInput in) throws IOException {
210211
explain = in.readBoolean();
211212
version = in.readBoolean();
212213
trackScores = in.readBoolean();
213-
storedFieldNames = (List<String>) in.readGenericValue();
214+
storedFieldsContext = in.readOptionalWriteable(StoredFieldsContext::new);
214215
docValueFields = (List<String>) in.readGenericValue();
215216
if (in.readBoolean()) {
216217
int size = in.readVInt();
@@ -248,14 +249,14 @@ public void writeTo(StreamOutput out) throws IOException {
248249
out.writeBoolean(explain);
249250
out.writeBoolean(version);
250251
out.writeBoolean(trackScores);
251-
out.writeGenericValue(storedFieldNames);
252+
out.writeOptionalWriteable(storedFieldsContext);
252253
out.writeGenericValue(docValueFields);
253254
boolean hasScriptFields = scriptFields != null;
254255
out.writeBoolean(hasScriptFields);
255256
if (hasScriptFields) {
256257
out.writeVInt(scriptFields.size());
257258
for (ScriptField scriptField : scriptFields) {
258-
scriptField.writeTo(out);;
259+
scriptField.writeTo(out);
259260
}
260261
}
261262
out.writeOptionalStreamable(fetchSourceContext);
@@ -343,39 +344,42 @@ public InnerHitBuilder setTrackScores(boolean trackScores) {
343344
/**
344345
* Gets the stored fields to load and return.
345346
*
346-
* @deprecated Use {@link InnerHitBuilder#getStoredFieldNames()} instead.
347+
* @deprecated Use {@link InnerHitBuilder#getStoredFieldsContext()} instead.
347348
*/
348349
@Deprecated
349350
public List<String> getFieldNames() {
350-
return storedFieldNames;
351+
return storedFieldsContext == null ? null : storedFieldsContext.fieldNames();
351352
}
352353

353354
/**
354-
* Sets the stored fields to load and return. If none
355-
* are specified, the source of the document will be returned.
355+
* Sets the stored fields to load and return.
356+
* If none are specified, the source of the document will be returned.
356357
*
357358
* @deprecated Use {@link InnerHitBuilder#setStoredFieldNames(List)} instead.
358359
*/
359360
@Deprecated
360361
public InnerHitBuilder setFieldNames(List<String> fieldNames) {
361-
this.storedFieldNames = fieldNames;
362-
return this;
362+
return setStoredFieldNames(fieldNames);
363363
}
364364

365365

366366
/**
367-
* Gets the stored fields to load and return.
367+
* Gets the stored fields context.
368368
*/
369-
public List<String> getStoredFieldNames() {
370-
return storedFieldNames;
369+
public StoredFieldsContext getStoredFieldsContext() {
370+
return storedFieldsContext;
371371
}
372372

373373
/**
374-
* Sets the stored fields to load and return. If none
375-
* are specified, the source of the document will be returned.
374+
* Sets the stored fields to load and return.
375+
* If none are specified, the source of the document will be returned.
376376
*/
377377
public InnerHitBuilder setStoredFieldNames(List<String> fieldNames) {
378-
this.storedFieldNames = fieldNames;
378+
if (storedFieldsContext == null) {
379+
storedFieldsContext = StoredFieldsContext.fromList(fieldNames);
380+
} else {
381+
storedFieldsContext.addFieldNames(fieldNames);
382+
}
379383
return this;
380384
}
381385

@@ -564,14 +568,8 @@ private void setupInnerHitsContext(QueryShardContext context, InnerHitsContext.B
564568
innerHitsContext.explain(explain);
565569
innerHitsContext.version(version);
566570
innerHitsContext.trackScores(trackScores);
567-
if (storedFieldNames != null) {
568-
if (storedFieldNames.isEmpty()) {
569-
innerHitsContext.emptyFieldNames();
570-
} else {
571-
for (String fieldName : storedFieldNames) {
572-
innerHitsContext.fieldNames().add(fieldName);
573-
}
574-
}
571+
if (storedFieldsContext != null) {
572+
innerHitsContext.storedFieldsContext(storedFieldsContext);
575573
}
576574
if (docValueFields != null) {
577575
DocValueFieldsContext docValueFieldsContext = innerHitsContext
@@ -633,16 +631,8 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
633631
if (fetchSourceContext != null) {
634632
builder.field(SearchSourceBuilder._SOURCE_FIELD.getPreferredName(), fetchSourceContext, params);
635633
}
636-
if (storedFieldNames != null) {
637-
if (storedFieldNames.size() == 1) {
638-
builder.field(SearchSourceBuilder.STORED_FIELDS_FIELD.getPreferredName(), storedFieldNames.get(0));
639-
} else {
640-
builder.startArray(SearchSourceBuilder.STORED_FIELDS_FIELD.getPreferredName());
641-
for (String fieldName : storedFieldNames) {
642-
builder.value(fieldName);
643-
}
644-
builder.endArray();
645-
}
634+
if (storedFieldsContext != null) {
635+
storedFieldsContext.toXContent(SearchSourceBuilder.STORED_FIELDS_FIELD.getPreferredName(), builder);
646636
}
647637
if (docValueFields != null) {
648638
builder.startArray(SearchSourceBuilder.DOCVALUE_FIELDS_FIELD.getPreferredName());
@@ -693,7 +683,7 @@ public boolean equals(Object o) {
693683
Objects.equals(explain, that.explain) &&
694684
Objects.equals(version, that.version) &&
695685
Objects.equals(trackScores, that.trackScores) &&
696-
Objects.equals(storedFieldNames, that.storedFieldNames) &&
686+
Objects.equals(storedFieldsContext, that.storedFieldsContext) &&
697687
Objects.equals(docValueFields, that.docValueFields) &&
698688
Objects.equals(scriptFields, that.scriptFields) &&
699689
Objects.equals(fetchSourceContext, that.fetchSourceContext) &&
@@ -705,7 +695,7 @@ public boolean equals(Object o) {
705695

706696
@Override
707697
public int hashCode() {
708-
return Objects.hash(name, nestedPath, parentChildType, from, size, explain, version, trackScores, storedFieldNames,
698+
return Objects.hash(name, nestedPath, parentChildType, from, size, explain, version, trackScores, storedFieldsContext,
709699
docValueFields, scriptFields, fetchSourceContext, sorts, highlightBuilder, query, childInnerHits);
710700
}
711701

core/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import org.elasticsearch.action.support.IndicesOptions;
2525
import org.elasticsearch.client.node.NodeClient;
2626
import org.elasticsearch.common.ParseFieldMatcher;
27-
import org.elasticsearch.common.ParsingException;
2827
import org.elasticsearch.common.Strings;
2928
import org.elasticsearch.common.bytes.BytesReference;
3029
import org.elasticsearch.common.inject.Inject;
@@ -33,7 +32,6 @@
3332
import org.elasticsearch.common.xcontent.XContentParser;
3433
import org.elasticsearch.index.query.QueryBuilder;
3534
import org.elasticsearch.index.query.QueryParseContext;
36-
import org.elasticsearch.indices.query.IndicesQueriesRegistry;
3735
import org.elasticsearch.rest.BaseRestHandler;
3836
import org.elasticsearch.rest.RestChannel;
3937
import org.elasticsearch.rest.RestController;
@@ -42,13 +40,12 @@
4240
import org.elasticsearch.rest.action.RestStatusToXContentListener;
4341
import org.elasticsearch.search.Scroll;
4442
import org.elasticsearch.search.SearchRequestParsers;
45-
import org.elasticsearch.search.aggregations.AggregatorParsers;
4643
import org.elasticsearch.search.builder.SearchSourceBuilder;
44+
import org.elasticsearch.search.fetch.StoredFieldsContext;
4745
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
4846
import org.elasticsearch.search.internal.SearchContext;
4947
import org.elasticsearch.search.sort.SortOrder;
5048
import org.elasticsearch.search.suggest.SuggestBuilder;
51-
import org.elasticsearch.search.suggest.Suggesters;
5249
import org.elasticsearch.search.suggest.term.TermSuggestionBuilder.SuggestMode;
5350

5451
import java.io.IOException;
@@ -178,18 +175,11 @@ private static void parseSearchSource(final SearchSourceBuilder searchSourceBuil
178175
"if the field is not stored");
179176
}
180177

181-
String sField = request.param("stored_fields");
182-
if (sField != null) {
183-
if (!Strings.hasText(sField)) {
184-
searchSourceBuilder.noStoredFields();
185-
} else {
186-
String[] sFields = Strings.splitStringByCommaToArray(sField);
187-
if (sFields != null) {
188-
for (String field : sFields) {
189-
searchSourceBuilder.storedField(field);
190-
}
191-
}
192-
}
178+
179+
StoredFieldsContext storedFieldsContext =
180+
StoredFieldsContext.fromRestRequest(SearchSourceBuilder.STORED_FIELDS_FIELD.getPreferredName(), request);
181+
if (storedFieldsContext != null) {
182+
searchSourceBuilder.storedFields(storedFieldsContext);
193183
}
194184
String sDocValueFields = request.param("docvalue_fields");
195185
if (sDocValueFields == null) {

core/src/main/java/org/elasticsearch/search/SearchService.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@
6767
import org.elasticsearch.search.fetch.ScrollQueryFetchSearchResult;
6868
import org.elasticsearch.search.fetch.ShardFetchRequest;
6969
import org.elasticsearch.search.fetch.subphase.DocValueFieldsContext;
70-
import org.elasticsearch.search.fetch.subphase.DocValueFieldsFetchSubPhase;
7170
import org.elasticsearch.search.fetch.subphase.DocValueFieldsContext.DocValueField;
71+
import org.elasticsearch.search.fetch.subphase.DocValueFieldsFetchSubPhase;
7272
import org.elasticsearch.search.fetch.subphase.ScriptFieldsContext.ScriptField;
7373
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
7474
import org.elasticsearch.search.internal.DefaultSearchContext;
@@ -729,9 +729,6 @@ private void parseSource(DefaultSearchContext context, SearchSourceBuilder sourc
729729
throw new SearchContextException(context, "failed to create RescoreSearchContext", e);
730730
}
731731
}
732-
if (source.storedFields() != null) {
733-
context.fieldNames().addAll(source.storedFields());
734-
}
735732
if (source.explain() != null) {
736733
context.explain(source.explain());
737734
}
@@ -823,6 +820,18 @@ private void parseSource(DefaultSearchContext context, SearchSourceBuilder sourc
823820
}
824821
context.sliceBuilder(source.slice());
825822
}
823+
824+
if (source.storedFields() != null) {
825+
if (source.storedFields().fetchFields() == false) {
826+
if (context.version()) {
827+
throw new SearchContextException(context, "`stored_fields` cannot be disabled if version is requested");
828+
}
829+
if (context.sourceRequested()) {
830+
throw new SearchContextException(context, "`stored_fields` cannot be disabled if _source is requested");
831+
}
832+
}
833+
context.storedFieldsContext(source.storedFields());
834+
}
826835
}
827836

828837
/**

0 commit comments

Comments
 (0)