Skip to content

Commit 91e3b3b

Browse files
committed
Acquire search in field caps only when needed
FieldCapabilitiesFetcher acquires a searcher to perform basic checks that don't actually require a searcher to be performed, as they are purely mappings driven. Instead, we can reuse the existing QueryRewriteContext to perform such checks and entirely avoid acquiring a searcher.
1 parent cc54010 commit 91e3b3b

File tree

3 files changed

+30
-59
lines changed

3 files changed

+30
-59
lines changed

server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesFetcher.java

Lines changed: 11 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,12 @@
1111

1212
import org.elasticsearch.cluster.metadata.MappingMetadata;
1313
import org.elasticsearch.core.Booleans;
14-
import org.elasticsearch.core.Nullable;
1514
import org.elasticsearch.index.IndexService;
16-
import org.elasticsearch.index.engine.Engine;
1715
import org.elasticsearch.index.mapper.MappedFieldType;
1816
import org.elasticsearch.index.mapper.RuntimeField;
1917
import org.elasticsearch.index.query.MatchAllQueryBuilder;
2018
import org.elasticsearch.index.query.QueryBuilder;
21-
import org.elasticsearch.index.query.SearchExecutionContext;
19+
import org.elasticsearch.index.query.QueryRewriteContext;
2220
import org.elasticsearch.index.shard.IndexShard;
2321
import org.elasticsearch.index.shard.ShardId;
2422
import org.elasticsearch.indices.IndicesService;
@@ -65,28 +63,11 @@ FieldCapabilitiesIndexResponse fetch(
6563
) throws IOException {
6664
final IndexService indexService = indicesService.indexServiceSafe(shardId.getIndex());
6765
final IndexShard indexShard = indexService.getShard(shardId.getId());
68-
final Engine.Searcher searcher;
6966
if (alwaysMatches(indexFilter)) {
7067
// no need to open a searcher if we aren't filtering, but make sure we are reading from an up-to-dated shard
7168
indexShard.readAllowed();
72-
searcher = null;
73-
} else {
74-
searcher = indexShard.acquireSearcher(Engine.CAN_MATCH_SEARCH_SOURCE);
75-
}
76-
try (searcher) {
77-
return doFetch(
78-
task,
79-
shardId,
80-
fieldNameFilter,
81-
filters,
82-
fieldTypes,
83-
indexFilter,
84-
nowInMillis,
85-
runtimeFields,
86-
indexService,
87-
searcher
88-
);
8969
}
70+
return doFetch(task, shardId, fieldNameFilter, filters, fieldTypes, indexFilter, nowInMillis, runtimeFields, indexService);
9071
}
9172

9273
private FieldCapabilitiesIndexResponse doFetch(
@@ -98,22 +79,13 @@ private FieldCapabilitiesIndexResponse doFetch(
9879
QueryBuilder indexFilter,
9980
long nowInMillis,
10081
Map<String, Object> runtimeFields,
101-
IndexService indexService,
102-
@Nullable Engine.Searcher searcher
82+
IndexService indexService
10383
) throws IOException {
104-
final SearchExecutionContext searchExecutionContext = indexService.newSearchExecutionContext(
105-
shardId.id(),
106-
0,
107-
searcher,
108-
() -> nowInMillis,
109-
null,
110-
runtimeFields
111-
);
112-
var indexMode = searchExecutionContext.getIndexSettings().getMode();
113-
if (searcher != null && canMatchShard(shardId, indexFilter, nowInMillis, searchExecutionContext) == false) {
84+
QueryRewriteContext queryRewriteContext = indexService.newQueryRewriteContext(() -> nowInMillis, runtimeFields, null);
85+
var indexMode = indexService.getIndexSettings().getMode();
86+
if (canMatchShard(shardId, indexFilter, nowInMillis, queryRewriteContext) == false) {
11487
return new FieldCapabilitiesIndexResponse(shardId.getIndexName(), null, Collections.emptyMap(), false, indexMode);
11588
}
116-
11789
final MappingMetadata mapping = indexService.getMetadata().mapping();
11890
String indexMappingHash;
11991
if (includeEmptyFields || enableFieldHasValue == false) {
@@ -135,7 +107,7 @@ private FieldCapabilitiesIndexResponse doFetch(
135107
}
136108
task.ensureNotCancelled();
137109
final Map<String, IndexFieldCapabilities> responseMap = retrieveFieldCaps(
138-
searchExecutionContext,
110+
queryRewriteContext,
139111
fieldNameFilter,
140112
filters,
141113
fieldTypes,
@@ -150,7 +122,7 @@ private FieldCapabilitiesIndexResponse doFetch(
150122
}
151123

152124
static Map<String, IndexFieldCapabilities> retrieveFieldCaps(
153-
SearchExecutionContext context,
125+
QueryRewriteContext context,
154126
Predicate<String> fieldNameFilter,
155127
String[] filters,
156128
String[] types,
@@ -236,20 +208,20 @@ private static boolean canMatchShard(
236208
ShardId shardId,
237209
QueryBuilder indexFilter,
238210
long nowInMillis,
239-
SearchExecutionContext searchExecutionContext
211+
QueryRewriteContext queryRewriteContext
240212
) throws IOException {
241213
assert alwaysMatches(indexFilter) == false : "should not be called for always matching [" + indexFilter + "]";
242214
assert nowInMillis != 0L;
243215
ShardSearchRequest searchRequest = new ShardSearchRequest(shardId, nowInMillis, AliasFilter.EMPTY);
244216
searchRequest.source(new SearchSourceBuilder().query(indexFilter));
245-
return SearchService.queryStillMatchesAfterRewrite(searchRequest, searchExecutionContext);
217+
return SearchService.queryStillMatchesAfterRewrite(searchRequest, queryRewriteContext);
246218
}
247219

248220
private static boolean alwaysMatches(QueryBuilder indexFilter) {
249221
return indexFilter == null || indexFilter instanceof MatchAllQueryBuilder;
250222
}
251223

252-
private static Predicate<MappedFieldType> buildFilter(String[] filters, String[] fieldTypes, SearchExecutionContext context) {
224+
private static Predicate<MappedFieldType> buildFilter(String[] filters, String[] fieldTypes, QueryRewriteContext context) {
253225
// security filters don't exclude metadata fields
254226
Predicate<MappedFieldType> fcf = null;
255227
if (fieldTypes.length > 0) {

server/src/main/java/org/elasticsearch/index/query/QueryRewriteContext.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.elasticsearch.index.mapper.MapperBuilderContext;
2727
import org.elasticsearch.index.mapper.MapperService;
2828
import org.elasticsearch.index.mapper.MappingLookup;
29+
import org.elasticsearch.index.mapper.NestedLookup;
2930
import org.elasticsearch.index.mapper.SourceFieldMapper;
3031
import org.elasticsearch.index.mapper.TextFieldMapper;
3132
import org.elasticsearch.plugins.internal.rewriter.QueryRewriteInterceptor;
@@ -465,4 +466,22 @@ public void setQueryRewriteInterceptor(QueryRewriteInterceptor queryRewriteInter
465466
this.queryRewriteInterceptor = queryRewriteInterceptor;
466467
}
467468

469+
public boolean isMetadataField(String field) {
470+
return mapperService.isMetadataField(field);
471+
}
472+
473+
public boolean isMultiField(String field) {
474+
if (runtimeMappings.containsKey(field)) {
475+
return false;
476+
}
477+
return mapperService.isMultiField(field);
478+
}
479+
480+
public NestedLookup nestedLookup() {
481+
return mappingLookup.nestedLookup();
482+
}
483+
484+
public boolean hasMappings() {
485+
return mappingLookup.hasMappings();
486+
}
468487
}

server/src/main/java/org/elasticsearch/index/query/SearchExecutionContext.java

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
import org.elasticsearch.index.mapper.MapperService;
4444
import org.elasticsearch.index.mapper.MappingLookup;
4545
import org.elasticsearch.index.mapper.MappingParserContext;
46-
import org.elasticsearch.index.mapper.NestedLookup;
4746
import org.elasticsearch.index.mapper.ParsedDocument;
4847
import org.elasticsearch.index.mapper.SourceLoader;
4948
import org.elasticsearch.index.mapper.SourceToParse;
@@ -372,32 +371,13 @@ public ParsedDocument parseDocument(SourceToParse source) throws DocumentParsing
372371
return mapperService.documentParser().parseDocument(source, mappingLookup);
373372
}
374373

375-
public NestedLookup nestedLookup() {
376-
return mappingLookup.nestedLookup();
377-
}
378-
379-
public boolean hasMappings() {
380-
return mappingLookup.hasMappings();
381-
}
382-
383374
/**
384375
* Returns true if the field identified by the provided name is mapped, false otherwise
385376
*/
386377
public boolean isFieldMapped(String name) {
387378
return fieldType(name) != null;
388379
}
389380

390-
public boolean isMetadataField(String field) {
391-
return mapperService.isMetadataField(field);
392-
}
393-
394-
public boolean isMultiField(String field) {
395-
if (runtimeMappings.containsKey(field)) {
396-
return false;
397-
}
398-
return mapperService.isMultiField(field);
399-
}
400-
401381
public Iterable<MappedFieldType> dimensionFields() {
402382
List<MappedFieldType> dimensionFields = new ArrayList<>();
403383
for (var mapper : mapperService.mappingLookup().fieldMappers()) {

0 commit comments

Comments
 (0)