diff --git a/docs/changelog/126137.yaml b/docs/changelog/126137.yaml new file mode 100644 index 0000000000000..c5e77171bbf48 --- /dev/null +++ b/docs/changelog/126137.yaml @@ -0,0 +1,5 @@ +pr: 126137 +summary: Acquire searcher in field caps only when needed +area: Search +type: bug +issues: [] diff --git a/server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesFetcher.java b/server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesFetcher.java index e6d7af11d06cc..d6c3b242b89b4 100644 --- a/server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesFetcher.java +++ b/server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesFetcher.java @@ -11,14 +11,12 @@ import org.elasticsearch.cluster.metadata.MappingMetadata; import org.elasticsearch.core.Booleans; -import org.elasticsearch.core.Nullable; import org.elasticsearch.index.IndexService; -import org.elasticsearch.index.engine.Engine; import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.RuntimeField; import org.elasticsearch.index.query.MatchAllQueryBuilder; import org.elasticsearch.index.query.QueryBuilder; -import org.elasticsearch.index.query.SearchExecutionContext; +import org.elasticsearch.index.query.QueryRewriteContext; import org.elasticsearch.index.shard.IndexShard; import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.indices.IndicesService; @@ -65,28 +63,11 @@ FieldCapabilitiesIndexResponse fetch( ) throws IOException { final IndexService indexService = indicesService.indexServiceSafe(shardId.getIndex()); final IndexShard indexShard = indexService.getShard(shardId.getId()); - final Engine.Searcher searcher; if (alwaysMatches(indexFilter)) { // no need to open a searcher if we aren't filtering, but make sure we are reading from an up-to-dated shard indexShard.readAllowed(); - searcher = null; - } else { - searcher = indexShard.acquireSearcher(Engine.CAN_MATCH_SEARCH_SOURCE); - } - try (searcher) { - return doFetch( - task, - shardId, - fieldNameFilter, - filters, - fieldTypes, - indexFilter, - nowInMillis, - runtimeFields, - indexService, - searcher - ); } + return doFetch(task, shardId, fieldNameFilter, filters, fieldTypes, indexFilter, nowInMillis, runtimeFields, indexService); } private FieldCapabilitiesIndexResponse doFetch( @@ -98,22 +79,13 @@ private FieldCapabilitiesIndexResponse doFetch( QueryBuilder indexFilter, long nowInMillis, Map runtimeFields, - IndexService indexService, - @Nullable Engine.Searcher searcher + IndexService indexService ) throws IOException { - final SearchExecutionContext searchExecutionContext = indexService.newSearchExecutionContext( - shardId.id(), - 0, - searcher, - () -> nowInMillis, - null, - runtimeFields - ); - var indexMode = searchExecutionContext.getIndexSettings().getMode(); - if (searcher != null && canMatchShard(shardId, indexFilter, nowInMillis, searchExecutionContext) == false) { + QueryRewriteContext queryRewriteContext = indexService.newQueryRewriteContext(() -> nowInMillis, runtimeFields, null); + var indexMode = indexService.getIndexSettings().getMode(); + if (canMatchShard(shardId, indexFilter, nowInMillis, queryRewriteContext) == false) { return new FieldCapabilitiesIndexResponse(shardId.getIndexName(), null, Collections.emptyMap(), false, indexMode); } - final MappingMetadata mapping = indexService.getMetadata().mapping(); String indexMappingHash; if (includeEmptyFields || enableFieldHasValue == false) { @@ -135,7 +107,7 @@ private FieldCapabilitiesIndexResponse doFetch( } task.ensureNotCancelled(); final Map responseMap = retrieveFieldCaps( - searchExecutionContext, + queryRewriteContext, fieldNameFilter, filters, fieldTypes, @@ -150,7 +122,7 @@ private FieldCapabilitiesIndexResponse doFetch( } static Map retrieveFieldCaps( - SearchExecutionContext context, + QueryRewriteContext context, Predicate fieldNameFilter, String[] filters, String[] types, @@ -236,20 +208,20 @@ private static boolean canMatchShard( ShardId shardId, QueryBuilder indexFilter, long nowInMillis, - SearchExecutionContext searchExecutionContext + QueryRewriteContext queryRewriteContext ) throws IOException { assert alwaysMatches(indexFilter) == false : "should not be called for always matching [" + indexFilter + "]"; assert nowInMillis != 0L; ShardSearchRequest searchRequest = new ShardSearchRequest(shardId, nowInMillis, AliasFilter.EMPTY); searchRequest.source(new SearchSourceBuilder().query(indexFilter)); - return SearchService.queryStillMatchesAfterRewrite(searchRequest, searchExecutionContext); + return SearchService.queryStillMatchesAfterRewrite(searchRequest, queryRewriteContext); } private static boolean alwaysMatches(QueryBuilder indexFilter) { return indexFilter == null || indexFilter instanceof MatchAllQueryBuilder; } - private static Predicate buildFilter(String[] filters, String[] fieldTypes, SearchExecutionContext context) { + private static Predicate buildFilter(String[] filters, String[] fieldTypes, QueryRewriteContext context) { // security filters don't exclude metadata fields Predicate fcf = null; if (fieldTypes.length > 0) { diff --git a/server/src/main/java/org/elasticsearch/index/query/QueryRewriteContext.java b/server/src/main/java/org/elasticsearch/index/query/QueryRewriteContext.java index bc14a31978c18..127b7c942b8c8 100644 --- a/server/src/main/java/org/elasticsearch/index/query/QueryRewriteContext.java +++ b/server/src/main/java/org/elasticsearch/index/query/QueryRewriteContext.java @@ -26,6 +26,7 @@ import org.elasticsearch.index.mapper.MapperBuilderContext; import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.MappingLookup; +import org.elasticsearch.index.mapper.NestedLookup; import org.elasticsearch.index.mapper.SourceFieldMapper; import org.elasticsearch.index.mapper.TextFieldMapper; import org.elasticsearch.plugins.internal.rewriter.QueryRewriteInterceptor; @@ -465,4 +466,22 @@ public void setQueryRewriteInterceptor(QueryRewriteInterceptor queryRewriteInter this.queryRewriteInterceptor = queryRewriteInterceptor; } + public boolean isMetadataField(String field) { + return mapperService.isMetadataField(field); + } + + public boolean isMultiField(String field) { + if (runtimeMappings.containsKey(field)) { + return false; + } + return mapperService.isMultiField(field); + } + + public NestedLookup nestedLookup() { + return mappingLookup.nestedLookup(); + } + + public boolean hasMappings() { + return mappingLookup.hasMappings(); + } } diff --git a/server/src/main/java/org/elasticsearch/index/query/SearchExecutionContext.java b/server/src/main/java/org/elasticsearch/index/query/SearchExecutionContext.java index bf1ac90101d86..49a0aeb303790 100644 --- a/server/src/main/java/org/elasticsearch/index/query/SearchExecutionContext.java +++ b/server/src/main/java/org/elasticsearch/index/query/SearchExecutionContext.java @@ -43,7 +43,6 @@ import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.MappingLookup; import org.elasticsearch.index.mapper.MappingParserContext; -import org.elasticsearch.index.mapper.NestedLookup; import org.elasticsearch.index.mapper.ParsedDocument; import org.elasticsearch.index.mapper.SourceLoader; import org.elasticsearch.index.mapper.SourceToParse; @@ -372,14 +371,6 @@ public ParsedDocument parseDocument(SourceToParse source) throws DocumentParsing return mapperService.documentParser().parseDocument(source, mappingLookup); } - public NestedLookup nestedLookup() { - return mappingLookup.nestedLookup(); - } - - public boolean hasMappings() { - return mappingLookup.hasMappings(); - } - /** * Returns true if the field identified by the provided name is mapped, false otherwise */ @@ -387,17 +378,6 @@ public boolean isFieldMapped(String name) { return fieldType(name) != null; } - public boolean isMetadataField(String field) { - return mapperService.isMetadataField(field); - } - - public boolean isMultiField(String field) { - if (runtimeMappings.containsKey(field)) { - return false; - } - return mapperService.isMultiField(field); - } - public Iterable dimensionFields() { List dimensionFields = new ArrayList<>(); for (var mapper : mapperService.mappingLookup().fieldMappers()) {