Skip to content

Commit fa7ac36

Browse files
[8.x] Only aggregations require at least one shard request (#115314) (#115794)
* Only aggregations require at least one shard request (#115314) * unskipping shards only when aggs * Update docs/changelog/115314.yaml * fixed more tests * null check for searchRequest.source() (cherry picked from commit 7f573c6) * applying #115774 * skipped test * fixed test --------- Co-authored-by: Elastic Machine <[email protected]>
1 parent 3e57a57 commit fa7ac36

File tree

17 files changed

+72
-57
lines changed

17 files changed

+72
-57
lines changed

docs/changelog/115314.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 115314
2+
summary: Only aggregations require at least one shard request
3+
area: Search
4+
type: enhancement
5+
issues: []

modules/data-streams/src/internalClusterTest/java/org/elasticsearch/datastreams/TSDBIndexingIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ public void testSkippingShards() throws Exception {
412412
assertResponse(client().search(searchRequest), searchResponse -> {
413413
ElasticsearchAssertions.assertNoSearchHits(searchResponse);
414414
assertThat(searchResponse.getTotalShards(), equalTo(2));
415-
assertThat(searchResponse.getSkippedShards(), equalTo(1));
415+
assertThat(searchResponse.getSkippedShards(), equalTo(2));
416416
assertThat(searchResponse.getSuccessfulShards(), equalTo(2));
417417
});
418418
}

qa/multi-cluster-search/src/test/java/org/elasticsearch/search/CCSDuelIT.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.elasticsearch.rest.action.search.RestSearchAction;
4444
import org.elasticsearch.script.Script;
4545
import org.elasticsearch.script.ScriptType;
46+
import org.elasticsearch.search.aggregations.AggregationBuilders;
4647
import org.elasticsearch.search.aggregations.BucketOrder;
4748
import org.elasticsearch.search.aggregations.bucket.filter.FilterAggregationBuilder;
4849
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramAggregationBuilder;
@@ -580,13 +581,14 @@ public void testSortByField() throws Exception {
580581

581582
public void testSortByFieldOneClusterHasNoResults() throws Exception {
582583
assumeMultiClusterSetup();
583-
// set to a value greater than the number of shards to avoid differences due to the skipping of shards
584+
// setting aggs to avoid differences due to the skipping of shards when matching none
584585
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
585586
boolean onlyRemote = randomBoolean();
586587
sourceBuilder.query(new TermQueryBuilder("_index", onlyRemote ? REMOTE_INDEX_NAME : INDEX_NAME));
587588
sourceBuilder.sort("type.keyword", SortOrder.ASC);
588589
sourceBuilder.sort("creationDate", SortOrder.DESC);
589590
sourceBuilder.sort("user.keyword", SortOrder.ASC);
591+
sourceBuilder.aggregation(AggregationBuilders.max("max").field("creationDate"));
590592
CheckedConsumer<ObjectPath, IOException> responseChecker = response -> {
591593
assertHits(response);
592594
int size = response.evaluateArraySize("hits.hits");

qa/multi-cluster-search/src/test/resources/rest-api-spec/test/multi_cluster/70_skip_shards.yml

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,7 @@
166166
- match: { hits.total.value: 0 }
167167
- match: { _shards.total: 2 }
168168
- match: { _shards.successful: 2 }
169-
# When all shards are skipped current logic returns 1 to produce a valid search result
170-
- match: { _shards.skipped : 1}
169+
- match: { _shards.skipped : 2}
171170
- match: { _shards.failed: 0 }
172171

173172
# check that skipped when we don't match the alias with a terms query
@@ -183,8 +182,7 @@
183182
- match: { hits.total.value: 0 }
184183
- match: { _shards.total: 2 }
185184
- match: { _shards.successful: 2 }
186-
# When all shards are skipped current logic returns 1 to produce a valid search result
187-
- match: { _shards.skipped : 1}
185+
- match: { _shards.skipped : 2}
188186
- match: { _shards.failed: 0 }
189187

190188
# check that skipped when we don't match the alias with a prefix query
@@ -200,8 +198,7 @@
200198
- match: { hits.total.value: 0 }
201199
- match: { _shards.total: 2 }
202200
- match: { _shards.successful: 2 }
203-
# When all shards are skipped current logic returns 1 to produce a valid search result
204-
- match: { _shards.skipped : 1}
201+
- match: { _shards.skipped : 2}
205202
- match: { _shards.failed: 0 }
206203

207204
# check that skipped when we don't match the alias with a wildcard query
@@ -217,7 +214,6 @@
217214
- match: { hits.total.value: 0 }
218215
- match: { _shards.total: 2 }
219216
- match: { _shards.successful: 2 }
220-
# When all shards are skipped current logic returns 1 to produce a valid search result
221-
- match: { _shards.skipped : 1}
217+
- match: { _shards.skipped : 2}
222218
- match: { _shards.failed: 0 }
223219

qa/multi-cluster-search/src/test/resources/rest-api-spec/test/multi_cluster/90_index_name_query.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ teardown:
8181
- match: { hits.total.value: 0 }
8282
- match: { _shards.total: 2 }
8383
- match: { _shards.successful: 2 }
84-
- match: { _shards.skipped : 1}
84+
- match: { _shards.skipped : 2}
8585
- match: { _shards.failed: 0 }
8686

8787
- do:
@@ -98,5 +98,5 @@ teardown:
9898
- match: { hits.total.value: 0 }
9999
- match: { _shards.total: 2 }
100100
- match: { _shards.successful: 2 }
101-
- match: { _shards.skipped : 1}
101+
- match: { _shards.skipped : 2}
102102
- match: { _shards.failed: 0 }

rest-api-spec/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ tasks.named("yamlRestTestV7CompatTransform").configure { task ->
8686
task.skipTest("search/240_date_nanos/doc value fields are working as expected across date and date_nanos fields", "Fetching docvalues field multiple times is no longer allowed")
8787
task.skipTest("search/110_field_collapsing/field collapsing and rescore", "#107779 Field collapsing is compatible with rescore in 8.15")
8888
task.skipTest("indices.create/11_basic_with_types/Create index with mappings", "Empty mapping creation has changed")
89+
task.skipTest("search/140_pre_filter_search_shards/pre_filter_shard_size with shards that have no hit", "#115314 we skipp all shards unless the query has aggs, therefore the _shard.skipped do not match")
8990

9091
task.replaceValueInMatch("_type", "_doc")
9192
task.addAllowedWarningRegex("\\[types removal\\].*")

server/src/internalClusterTest/java/org/elasticsearch/search/ccs/CrossClusterSearchIT.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ public void testCCSClusterDetailsWhereAllShardsSkippedInCanMatch() throws Except
214214
// with DFS_QUERY_THEN_FETCH, the local shards are never skipped
215215
assertThat(localClusterSearchInfo.getSkippedShards(), equalTo(0));
216216
} else {
217-
assertThat(localClusterSearchInfo.getSkippedShards(), equalTo(localNumShards - 1));
217+
assertThat(localClusterSearchInfo.getSkippedShards(), equalTo(localNumShards));
218218
}
219219
assertThat(localClusterSearchInfo.getFailedShards(), equalTo(0));
220220
assertThat(localClusterSearchInfo.getFailures().size(), equalTo(0));
@@ -224,7 +224,7 @@ public void testCCSClusterDetailsWhereAllShardsSkippedInCanMatch() throws Except
224224
assertThat(remoteClusterSearchInfo.getTotalShards(), equalTo(remoteNumShards));
225225
assertThat(remoteClusterSearchInfo.getSuccessfulShards(), equalTo(remoteNumShards));
226226
if (clusters.isCcsMinimizeRoundtrips()) {
227-
assertThat(remoteClusterSearchInfo.getSkippedShards(), equalTo(remoteNumShards - 1));
227+
assertThat(remoteClusterSearchInfo.getSkippedShards(), equalTo(remoteNumShards));
228228
} else {
229229
assertThat(remoteClusterSearchInfo.getSkippedShards(), equalTo(remoteNumShards));
230230
}

server/src/internalClusterTest/java/org/elasticsearch/search/profile/query/QueryProfilerIT.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,11 @@ public void testProfileQuery() throws Exception {
6868
prepareSearch().setQuery(q).setTrackTotalHits(true).setProfile(true).setSearchType(SearchType.QUERY_THEN_FETCH),
6969
response -> {
7070
assertNotNull("Profile response element should not be null", response.getProfileResults());
71-
assertThat("Profile response should not be an empty array", response.getProfileResults().size(), not(0));
71+
if (response.getSkippedShards() == response.getSuccessfulShards()) {
72+
assertEquals(0, response.getProfileResults().size());
73+
} else {
74+
assertThat("Profile response should not be an empty array", response.getProfileResults().size(), not(0));
75+
}
7276
for (Map.Entry<String, SearchProfileShardResult> shard : response.getProfileResults().entrySet()) {
7377
for (QueryProfileShardResult searchProfiles : shard.getValue().getQueryProfileResults()) {
7478
for (ProfileResult result : searchProfiles.getQueryResults()) {

server/src/internalClusterTest/java/org/elasticsearch/search/stats/FieldUsageStatsIT.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,15 @@ public void testFieldUsageStats() throws ExecutionException, InterruptedExceptio
158158

159159
assertTrue(stats.hasField("date_field"));
160160
assertEquals(Set.of(UsageContext.POINTS), stats.get("date_field").keySet());
161-
// can_match does not enter search stats
162-
// there is a special case though where we have no hit but we need to get at least one search response in order
163-
// to produce a valid search result with all the aggs etc., so we hit one of the two shards
161+
162+
long expectedShards = 2L * numShards;
163+
if (numShards == 1) {
164+
// with 1 shard and setPreFilterShardSize(1) we don't perform can_match phase but instead directly query the shard
165+
expectedShards += 1;
166+
}
167+
164168
assertEquals(
165-
(2 * numShards) + 1,
169+
expectedShards,
166170
indicesAdmin().prepareStats("test")
167171
.clear()
168172
.setSearch(true)

server/src/main/java/org/elasticsearch/action/search/TransportSearchAction.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1457,6 +1457,8 @@ public SearchPhase newSearchPhase(
14571457
SearchResponse.Clusters clusters
14581458
) {
14591459
if (preFilter) {
1460+
// only for aggs we need to contact shards even if there are no matches
1461+
boolean requireAtLeastOneMatch = searchRequest.source() != null && searchRequest.source().aggregations() != null;
14601462
return new CanMatchPreFilterSearchPhase(
14611463
logger,
14621464
searchTransportService,
@@ -1468,7 +1470,7 @@ public SearchPhase newSearchPhase(
14681470
shardIterators,
14691471
timeProvider,
14701472
task,
1471-
true,
1473+
requireAtLeastOneMatch,
14721474
searchService.getCoordinatorRewriteContextProvider(timeProvider::absoluteStartMillis),
14731475
listener.delegateFailureAndWrap(
14741476
(l, iters) -> newSearchPhase(

0 commit comments

Comments
 (0)