diff --git a/server/src/main/java/org/elasticsearch/action/search/AbstractSearchAsyncAction.java b/server/src/main/java/org/elasticsearch/action/search/AbstractSearchAsyncAction.java index 73e6a0306247d..f1d612cd0fe85 100644 --- a/server/src/main/java/org/elasticsearch/action/search/AbstractSearchAsyncAction.java +++ b/server/src/main/java/org/elasticsearch/action/search/AbstractSearchAsyncAction.java @@ -769,7 +769,7 @@ public final void execute(Runnable command) { * tiebreak results with identical sort values */ protected final ShardSearchRequest buildShardSearchRequest(SearchShardIterator shardIt, int shardIndex) { - AliasFilter filter = aliasFilter.get(shardIt.shardId().getIndex().getUUID()); + AliasFilter filter = aliasFilter.getOrDefault(shardIt.shardId().getIndex().getUUID(), AliasFilter.EMPTY); assert filter != null; float indexBoost = concreteIndexBoosts.getOrDefault(shardIt.shardId().getIndex().getUUID(), DEFAULT_INDEX_BOOST); ShardSearchRequest shardRequest = new ShardSearchRequest( diff --git a/server/src/main/java/org/elasticsearch/action/search/CanMatchPreFilterSearchPhase.java b/server/src/main/java/org/elasticsearch/action/search/CanMatchPreFilterSearchPhase.java index d45a8a6f01cd1..6a2b7037ce553 100644 --- a/server/src/main/java/org/elasticsearch/action/search/CanMatchPreFilterSearchPhase.java +++ b/server/src/main/java/org/elasticsearch/action/search/CanMatchPreFilterSearchPhase.java @@ -376,16 +376,13 @@ private void finishPhase() { private static final float DEFAULT_INDEX_BOOST = 1.0f; public CanMatchNodeRequest.Shard buildShardLevelRequest(SearchShardIterator shardIt) { - AliasFilter filter = aliasFilter.get(shardIt.shardId().getIndex().getUUID()); - assert filter != null; - float indexBoost = concreteIndexBoosts.getOrDefault(shardIt.shardId().getIndex().getUUID(), DEFAULT_INDEX_BOOST); int shardRequestIndex = shardItIndexMap.get(shardIt); return new CanMatchNodeRequest.Shard( shardIt.getOriginalIndices().indices(), shardIt.shardId(), shardRequestIndex, - filter, - indexBoost, + aliasFilter.getOrDefault(shardIt.shardId().getIndex().getUUID(), AliasFilter.EMPTY), + concreteIndexBoosts.getOrDefault(shardIt.shardId().getIndex().getUUID(), DEFAULT_INDEX_BOOST), shardIt.getSearchContextId(), shardIt.getSearchContextKeepAlive(), ShardSearchRequest.computeWaitForCheckpoint(request.getWaitForCheckpoints(), shardIt.shardId(), shardRequestIndex) diff --git a/server/src/main/java/org/elasticsearch/action/search/TransportSearchAction.java b/server/src/main/java/org/elasticsearch/action/search/TransportSearchAction.java index 70a7f4c8cad0c..936ea1a3359fb 100644 --- a/server/src/main/java/org/elasticsearch/action/search/TransportSearchAction.java +++ b/server/src/main/java/org/elasticsearch/action/search/TransportSearchAction.java @@ -259,14 +259,17 @@ private static boolean hasDataStreamRef(ClusterState clusterState, Set i Map buildIndexAliasFilters( ClusterState clusterState, Set indicesAndAliases, - Index[] concreteIndices + Index[] concreteIndices, + boolean filterEmpty ) { final Map aliasFilterMap = new HashMap<>(); for (Index index : concreteIndices) { clusterState.blocks().indexBlockedRaiseException(ClusterBlockLevel.READ, index.getName()); AliasFilter aliasFilter = searchService.buildAliasFilter(clusterState, index.getName(), indicesAndAliases); assert aliasFilter != null; - aliasFilterMap.put(index.getUUID(), aliasFilter); + if (filterEmpty == false || aliasFilter != AliasFilter.EMPTY) { + aliasFilterMap.put(index.getUUID(), aliasFilter); + } } return aliasFilterMap; } @@ -1087,7 +1090,7 @@ static List getRemoteShardsIterator( // add the cluster name to the remote index names for indices disambiguation // this ends up in the hits returned with the search response ShardId shardId = searchShardsGroup.shardId(); - AliasFilter aliasFilter = aliasFilterMap.get(shardId.getIndex().getUUID()); + AliasFilter aliasFilter = aliasFilterMap.getOrDefault(shardId.getIndex().getUUID(), AliasFilter.EMPTY); String[] aliases = aliasFilter.getAliases(); String clusterAlias = entry.getKey(); String[] finalIndices = aliases.length == 0 ? new String[] { shardId.getIndexName() } : aliases; @@ -1247,7 +1250,7 @@ private void executeSearch( clusterState, searchRequest.indices() ); - aliasFilter = buildIndexAliasFilters(clusterState, indicesAndAliases, indices); + aliasFilter = buildIndexAliasFilters(clusterState, indicesAndAliases, indices, true); aliasFilter.putAll(remoteAliasMap); localShardIterators = getLocalShardsIterator( clusterState, diff --git a/server/src/main/java/org/elasticsearch/action/search/TransportSearchShardsAction.java b/server/src/main/java/org/elasticsearch/action/search/TransportSearchShardsAction.java index 614a3e9cf22ae..e81155f52b891 100644 --- a/server/src/main/java/org/elasticsearch/action/search/TransportSearchShardsAction.java +++ b/server/src/main/java/org/elasticsearch/action/search/TransportSearchShardsAction.java @@ -135,7 +135,8 @@ public void searchShards(Task task, SearchShardsRequest searchShardsRequest, Act final Map aliasFilters = transportSearchAction.buildIndexAliasFilters( clusterState, indicesAndAliases, - concreteIndices + concreteIndices, + false ); String[] concreteIndexNames = Arrays.stream(concreteIndices).map(Index::getName).toArray(String[]::new); GroupShardsIterator shardIts = GroupShardsIterator.sortAndCreate( diff --git a/server/src/main/java/org/elasticsearch/indices/IndicesService.java b/server/src/main/java/org/elasticsearch/indices/IndicesService.java index 0a3baf2c52f57..4468250e34942 100644 --- a/server/src/main/java/org/elasticsearch/indices/IndicesService.java +++ b/server/src/main/java/org/elasticsearch/indices/IndicesService.java @@ -34,11 +34,9 @@ import org.elasticsearch.client.internal.Client; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.DataStream; -import org.elasticsearch.cluster.metadata.IndexAbstraction; import org.elasticsearch.cluster.metadata.IndexMetadata; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver.ResolvedExpression; -import org.elasticsearch.cluster.metadata.Metadata; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.routing.RecoverySource; import org.elasticsearch.cluster.routing.ShardRouting; @@ -49,6 +47,7 @@ import org.elasticsearch.common.breaker.CircuitBreaker; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.component.AbstractLifecycleComponent; +import org.elasticsearch.common.compress.CompressedXContent; import org.elasticsearch.common.io.FileSystemUtils; import org.elasticsearch.common.io.stream.BytesStreamOutput; import org.elasticsearch.common.io.stream.NamedWriteableAwareStreamInput; @@ -1717,52 +1716,56 @@ interface IndexDeletionAllowedPredicate { private final IndexDeletionAllowedPredicate ALWAYS_TRUE = (Index index, IndexSettings indexSettings) -> true; public AliasFilter buildAliasFilter(ClusterState state, String index, Set resolvedExpressions) { - /* Being static, parseAliasFilter doesn't have access to whatever guts it needs to parse a query. Instead of passing in a bunch - * of dependencies we pass in a function that can perform the parsing. */ - CheckedFunction filterParser = bytes -> { - try ( - XContentParser parser = XContentHelper.createParserNotCompressed(parserConfig, bytes, XContentHelper.xContentType(bytes)) - ) { - return parseTopLevelQuery(parser); - } - }; String[] aliases = indexNameExpressionResolver.filteringAliases(state, index, resolvedExpressions); if (aliases == null) { return AliasFilter.EMPTY; } - Metadata metadata = state.metadata(); - IndexAbstraction ia = state.metadata().getIndicesLookup().get(index); - DataStream dataStream = ia.getParentDataStream(); - if (dataStream != null) { - String dataStreamName = dataStream.getName(); - List filters = Arrays.stream(aliases) - .map(name -> metadata.dataStreamAliases().get(name)) - .filter(dataStreamAlias -> dataStreamAlias.getFilter(dataStreamName) != null) - .map(dataStreamAlias -> { - try { - return filterParser.apply(dataStreamAlias.getFilter(dataStreamName).uncompressed()); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - }) - .toList(); - if (filters.isEmpty()) { - return AliasFilter.of(null, aliases); - } else { - if (filters.size() == 1) { - return AliasFilter.of(filters.get(0), aliases); - } else { - BoolQueryBuilder bool = new BoolQueryBuilder(); - for (QueryBuilder filter : filters) { - bool.should(filter); - } - return AliasFilter.of(bool, aliases); + return doBuildAliasFilter(state, index, aliases); + } + + private AliasFilter doBuildAliasFilter(ClusterState state, String index, String[] aliases) { + DataStream dataStream = state.metadata().getIndicesLookup().get(index).getParentDataStream(); + if (dataStream == null) { + return AliasFilter.of(ShardSearchRequest.parseAliasFilter(this::parseFilter, state.metadata().index(index), aliases), aliases); + } + var dataStreamAliases = state.metadata().dataStreamAliases(); + String dataStreamName = dataStream.getName(); + List filters = Arrays.stream(aliases) + .map(dataStreamAliases::get) + .filter(dataStreamAlias -> dataStreamAlias.getFilter(dataStreamName) != null) + .map(dataStreamAlias -> { + try { + return parseFilter(dataStreamAlias.getFilter(dataStreamName)); + } catch (IOException e) { + throw new UncheckedIOException(e); } - } - } else { - IndexMetadata indexMetadata = metadata.index(index); - return AliasFilter.of(ShardSearchRequest.parseAliasFilter(filterParser, indexMetadata, aliases), aliases); + }) + .toList(); + + if (filters.isEmpty()) { + return AliasFilter.of(null, aliases); + } + if (filters.size() == 1) { + return AliasFilter.of(filters.get(0), aliases); + } + BoolQueryBuilder bool = new BoolQueryBuilder(); + for (QueryBuilder filter : filters) { + bool.should(filter); + } + return AliasFilter.of(bool, aliases); + } + + private QueryBuilder parseFilter(CompressedXContent bytes) throws IOException { + var uncompressed = bytes.uncompressed(); + try ( + XContentParser parser = XContentHelper.createParserNotCompressed( + parserConfig, + uncompressed, + XContentHelper.xContentType(uncompressed) + ) + ) { + return parseTopLevelQuery(parser); } } diff --git a/server/src/main/java/org/elasticsearch/search/internal/ShardSearchRequest.java b/server/src/main/java/org/elasticsearch/search/internal/ShardSearchRequest.java index 5e4ffbdba9ad2..97c4d81210090 100644 --- a/server/src/main/java/org/elasticsearch/search/internal/ShardSearchRequest.java +++ b/server/src/main/java/org/elasticsearch/search/internal/ShardSearchRequest.java @@ -23,6 +23,7 @@ import org.elasticsearch.common.Strings; import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.compress.CompressedXContent; import org.elasticsearch.common.hash.MessageDigests; import org.elasticsearch.common.io.stream.BytesStreamOutput; import org.elasticsearch.common.io.stream.StreamInput; @@ -621,7 +622,7 @@ public Rewriteable rewrite(QueryRewriteContext ctx) throws IOException { * Returns {@code null} if no filtering is required.

*/ public static QueryBuilder parseAliasFilter( - CheckedFunction filterParser, + CheckedFunction filterParser, IndexMetadata metadata, String... aliasNames ) { @@ -635,7 +636,7 @@ public static QueryBuilder parseAliasFilter( return null; } try { - return filterParser.apply(alias.filter().uncompressed()); + return filterParser.apply(alias.filter()); } catch (IOException ex) { throw new AliasFilterParsingException(index, alias.getAlias(), "Invalid alias filter", ex); } diff --git a/server/src/test/java/org/elasticsearch/search/internal/ShardSearchRequestTests.java b/server/src/test/java/org/elasticsearch/search/internal/ShardSearchRequestTests.java index 5ff6e04648c87..a4f4861b05d63 100644 --- a/server/src/test/java/org/elasticsearch/search/internal/ShardSearchRequestTests.java +++ b/server/src/test/java/org/elasticsearch/search/internal/ShardSearchRequestTests.java @@ -210,7 +210,7 @@ private IndexMetadata add(IndexMetadata indexMetadata, String alias, @Nullable C public QueryBuilder aliasFilter(IndexMetadata indexMetadata, String... aliasNames) { return ShardSearchRequest.parseAliasFilter(bytes -> { try ( - InputStream inputStream = bytes.streamInput(); + InputStream inputStream = bytes.uncompressed().streamInput(); XContentParser parser = XContentFactory.xContentType(inputStream) .xContent() .createParser(xContentRegistry(), DeprecationHandler.THROW_UNSUPPORTED_OPERATION, inputStream)