@@ -401,11 +401,13 @@ private static ShardSearchRequest tryRewriteWithUpdatedSortValue(
401401 // disable tracking total hits if we already reached the required estimation.
402402 if (trackTotalHitsUpTo != SearchContext .TRACK_TOTAL_HITS_ACCURATE && bottomSortCollector .getTotalHits () > trackTotalHitsUpTo ) {
403403 request .source (request .source ().shallowCopy ().trackTotalHits (false ));
404+ request .setRunCanMatchInQueryPhase (true );
404405 }
405406
406407 // set the current best bottom field doc
407408 if (bottomSortCollector .getBottomSortValues () != null ) {
408409 request .setBottomSortValues (bottomSortCollector .getBottomSortValues ());
410+ request .setRunCanMatchInQueryPhase (true );
409411 }
410412 return request ;
411413 }
@@ -467,30 +469,32 @@ protected void doRun(Map<SearchShardIterator, Integer> shardIndexMap) {
467469 transportService .getThreadPool ().executor (ThreadPool .Names .SEARCH_COORDINATION ).execute (new AbstractRunnable () {
468470 @ Override
469471 protected void doRun () {
470- if (hasPrimaryFieldSort (request .source ())) {
472+ var shards = localNodeRequest .shards ;
473+ if (shards .size () > 1 && hasPrimaryFieldSort (request .source ())) {
471474 @ SuppressWarnings ("rawtypes" )
472- final MinAndMax [] minAndMax = new MinAndMax [localNodeRequest . shards .size ()];
475+ final MinAndMax [] minAndMax = new MinAndMax [shards .size ()];
473476 for (int i = 0 ; i < minAndMax .length ; i ++) {
474- minAndMax [ i ] = searchService . canMatch (
475- buildShardSearchRequestForLocal (localNodeRequest , localNodeRequest . shards .get (i ))
476- ) .estimatedMinAndMax ();
477+ // TODO: refactor to avoid building the search request twice, here and then when actually executing the query
478+ minAndMax [ i ] = searchService . canMatch ( buildShardSearchRequestForLocal (localNodeRequest , shards .get (i ) ))
479+ .estimatedMinAndMax ();
477480 }
481+
478482 try {
479- int [] indexes = CanMatchPreFilterSearchPhase .sortShards (
480- localNodeRequest . shards ,
483+ final int [] indexes = CanMatchPreFilterSearchPhase .sortShards (
484+ shards ,
481485 minAndMax ,
482486 FieldSortBuilder .getPrimaryFieldSortOrNull (request .source ()).order ()
483487 );
488+ final ShardToQuery [] orig = shards .toArray (new ShardToQuery [0 ]);
484489 for (int i = 0 ; i < indexes .length ; i ++) {
485- ShardToQuery shardToQuery = localNodeRequest .shards .get (i );
486- shardToQuery = localNodeRequest .shards .set (i , shardToQuery );
487- localNodeRequest .shards .set (i , shardToQuery );
490+ shards .set (i , orig [indexes [i ]]);
488491 }
489492 } catch (Exception e ) {
490493 // ignored, field type conflicts will be dealt with in upstream logic
491494 // TODO: we should fail the query here, we're already seeing a field type conflict on the sort field,
492495 // no need to actually execute the queries and go through a lot of work before we inevitably have to
493496 // fail the search
497+
494498 }
495499 }
496500 executeWithoutBatching (localTarget , localNodeRequest );
@@ -650,14 +654,21 @@ static void registerNodeSearchAction(
650654 final SearchRequest searchRequest = request .searchRequest ;
651655 final IntUnaryOperator shards ;
652656 final ShardSearchRequest [] shardSearchRequests ;
653- if (hasPrimaryFieldSort (searchRequest .source ())) {
654- shardSearchRequests = new ShardSearchRequest [request .shards .size ()];
657+ final int shardCount = request .shards .size ();
658+ if (shardCount > 1 && hasPrimaryFieldSort (searchRequest .source ())) {
659+ shardSearchRequests = new ShardSearchRequest [shardCount ];
655660 @ SuppressWarnings ("rawtypes" )
656- final MinAndMax [] minAndMax = new MinAndMax [request . shards . size () ];
661+ final MinAndMax [] minAndMax = new MinAndMax [shardCount ];
657662 for (int i = 0 ; i < minAndMax .length ; i ++) {
658663 ShardSearchRequest r = buildShardSearchRequestForLocal (request , request .shards .get (i ));
659664 shardSearchRequests [i ] = r ;
660- minAndMax [i ] = searchService .canMatch (r ).estimatedMinAndMax ();
665+ var canMatch = searchService .canMatch (r );
666+ if (canMatch .canMatch ()) {
667+ r .setRunCanMatchInQueryPhase (false );
668+ minAndMax [i ] = canMatch .estimatedMinAndMax ();
669+ } else {
670+ assert false ;
671+ }
661672 }
662673 int [] indexes = CanMatchPreFilterSearchPhase .sortShards (
663674 request .shards ,
@@ -670,11 +681,10 @@ static void registerNodeSearchAction(
670681 shards = IntUnaryOperator .identity ();
671682 }
672683 final CancellableTask cancellableTask = (CancellableTask ) task ;
673- final int shardCount = request .shards .size ();
674- int workers = Math .min (request .searchRequest .getMaxConcurrentShardRequests (), Math .min (shardCount , searchPoolMax ));
684+ int workers = Math .min (searchRequest .getMaxConcurrentShardRequests (), Math .min (shardCount , searchPoolMax ));
675685 final var state = new QueryPerNodeState (
676686 new QueryPhaseResultConsumer (
677- request . searchRequest ,
687+ searchRequest ,
678688 dependencies .executor ,
679689 searchService .getCircuitBreaker (),
680690 searchPhaseController ,
0 commit comments