8383import org .opensearch .index .query .InnerHitContextBuilder ;
8484import org .opensearch .index .query .MatchAllQueryBuilder ;
8585import org .opensearch .index .query .MatchNoneQueryBuilder ;
86- import org .opensearch .index .query .QueryBuilder ;
8786import org .opensearch .index .query .QueryRewriteContext ;
8887import org .opensearch .index .query .QueryShardContext ;
8988import org .opensearch .index .query .Rewriteable ;
@@ -1597,8 +1596,7 @@ public CanMatchResponse canMatch(ShardSearchRequest request) throws IOException
15971596 private CanMatchResponse canMatch (ShardSearchRequest request , boolean checkRefreshPending ) throws IOException {
15981597 assert request .searchType () == SearchType .QUERY_THEN_FETCH : "unexpected search type: " + request .searchType ();
15991598 final ReaderContext readerContext = request .readerId () != null ? findReaderContext (request .readerId (), request ) : null ;
1600- final Releasable markAsUsed = readerContext != null ? readerContext .markAsUsed (getKeepAlive (request )) : () -> {};
1601- try (Releasable ignored = markAsUsed ) {
1599+ try (Releasable ignored = readerContext != null ? readerContext .markAsUsed (getKeepAlive (request )) : () -> {}) {
16021600 final IndexService indexService ;
16031601 final Engine .Searcher canMatchSearcher ;
16041602 final boolean hasRefreshPending ;
@@ -1621,22 +1619,34 @@ private CanMatchResponse canMatch(ShardSearchRequest request, boolean checkRefre
16211619 request .getClusterAlias ()
16221620 );
16231621 Rewriteable .rewrite (request .getRewriteable (), context , false );
1622+
1623+ if (hasRefreshPending ) {
1624+ final FieldSortBuilder sortBuilder = FieldSortBuilder .getPrimaryFieldSortOrNull (request .source ());
1625+ final MinAndMax <?> minMax = sortBuilder != null ? FieldSortBuilder .getMinMaxOrNull (context , sortBuilder ) : null ;
1626+ return new CanMatchResponse (true , minMax );
1627+ }
1628+
16241629 final boolean aliasFilterCanMatch = request .getAliasFilter ().getQueryBuilder () instanceof MatchNoneQueryBuilder == false ;
1625- FieldSortBuilder sortBuilder = FieldSortBuilder . getPrimaryFieldSortOrNull ( request . source ());
1626- MinAndMax <?> minMax = sortBuilder != null ? FieldSortBuilder . getMinMaxOrNull ( context , sortBuilder ) : null ;
1627- boolean canMatch ;
1628- if ( canRewriteToMatchNone ( request . source ())) {
1629- QueryBuilder queryBuilder = request . source (). query ();
1630- canMatch = aliasFilterCanMatch && queryBuilder instanceof MatchNoneQueryBuilder == false ;
1631- } else {
1632- // null query means match_all
1633- canMatch = aliasFilterCanMatch ;
1630+ if ( aliasFilterCanMatch == false ) {
1631+ return new CanMatchResponse ( false , null ) ;
1632+ }
1633+
1634+ // null query means match_all
1635+ boolean canMatch = canRewriteToMatchNone ( request . source ()) == false
1636+ || request . source (). query () instanceof MatchNoneQueryBuilder == false ;
1637+ if ( canMatch == false ) {
1638+ return new CanMatchResponse ( false , null ) ;
16341639 }
1635- final FieldDoc searchAfterFieldDoc = getSearchAfterFieldDoc (request , context );
1636- final Integer trackTotalHitsUpto = request .source () == null ? null : request .source ().trackTotalHitsUpTo ();
1637- canMatch = canMatch && canMatchSearchAfter (searchAfterFieldDoc , minMax , sortBuilder , trackTotalHitsUpto );
16381640
1639- return new CanMatchResponse (canMatch || hasRefreshPending , minMax );
1641+ final FieldSortBuilder sortBuilder = FieldSortBuilder .getPrimaryFieldSortOrNull (request .source ());
1642+ final MinAndMax <?> minMax = sortBuilder != null ? FieldSortBuilder .getMinMaxOrNull (context , sortBuilder ) : null ;
1643+ final Object primarySearchAfterField = SearchAfterBuilder .getPrimarySearchAfterFieldOrNull (request .source ());
1644+ if (minMax != null && primarySearchAfterField != null ) {
1645+ final FieldDoc searchAfterFieldDoc = getPrimarySearchAfterFieldDoc (sortBuilder , primarySearchAfterField , context );
1646+ final Integer trackTotalHitsUpto = request .source () == null ? null : request .source ().trackTotalHitsUpTo ();
1647+ canMatch = canMatchSearchAfter (searchAfterFieldDoc , minMax , sortBuilder , trackTotalHitsUpto );
1648+ }
1649+ return new CanMatchResponse (canMatch , minMax );
16401650 }
16411651 }
16421652 }
@@ -1672,16 +1682,14 @@ public static boolean canMatchSearchAfter(
16721682 return true ;
16731683 }
16741684
1675- private static FieldDoc getSearchAfterFieldDoc (ShardSearchRequest request , QueryShardContext context ) throws IOException {
1676- if (context != null && request != null && request .source () != null && request .source ().sorts () != null ) {
1677- final List <SortBuilder <?>> sorts = request .source ().sorts ();
1678- final Object [] searchAfter = request .source ().searchAfter ();
1679- final Optional <SortAndFormats > sortOpt = SortBuilder .buildSort (sorts , context );
1680- if (sortOpt .isPresent () && !CollectionUtils .isEmpty (searchAfter )) {
1681- return SearchAfterBuilder .buildFieldDoc (sortOpt .get (), searchAfter );
1682- }
1683- }
1684- return null ;
1685+ private static FieldDoc getPrimarySearchAfterFieldDoc (
1686+ FieldSortBuilder primarySortBuilder ,
1687+ Object primarySearchAfter ,
1688+ QueryShardContext context
1689+ ) throws IOException {
1690+ final Optional <SortAndFormats > sortOpt = SortBuilder .buildSort (List .of (primarySortBuilder ), context );
1691+ return sortOpt .map (sortAndFormats -> SearchAfterBuilder .buildFieldDoc (sortAndFormats , new Object [] { primarySearchAfter }))
1692+ .orElse (null );
16851693 }
16861694
16871695 /**
0 commit comments