Просмотр исходного кода

Always set terminated_early if terminate_after is set in the search request (#40839)

* terminated_early should always be set in the response with terminate_after

Today we set `terminated_early` to true in the response if the query terminated
early due to `terminate_after`. However if `terminate_after` is smaller than
the number of documents in a shard we don't set the flag in the response indicating
that the query was exhaustive. This change fixes this disprepancy by setting
terminated_early to false in the response if the number of documents that match
the query is smaller than the provided `terminate_after` value.

Closes #33949
Jim Ferenczi 6 лет назад
Родитель
Сommit
f15a1cdbc5

+ 4 - 0
server/src/main/java/org/elasticsearch/search/query/QueryPhase.java

@@ -281,6 +281,10 @@ public class QueryPhase implements SearchPhase {
             } finally {
                 searchContext.clearReleasables(SearchContext.Lifetime.COLLECTION);
             }
+            if (searchContext.terminateAfter() != SearchContext.DEFAULT_TERMINATE_AFTER
+                    && queryResult.terminatedEarly() == null) {
+                queryResult.terminatedEarly(false);
+            }
 
             final QuerySearchResult result = searchContext.queryResult();
             for (QueryCollectorContext ctx : collectors) {

+ 13 - 2
server/src/test/java/org/elasticsearch/search/query/QueryPhaseTests.java

@@ -353,11 +353,23 @@ public class QueryPhaseTests extends IndexShardTestCase {
         TestSearchContext context = new TestSearchContext(null, indexShard);
         context.setTask(new SearchTask(123L, "", "", "", null, Collections.emptyMap()));
         context.parsedQuery(new ParsedQuery(new MatchAllDocsQuery()));
-        context.terminateAfter(1);
 
         final IndexReader reader = DirectoryReader.open(dir);
         IndexSearcher contextSearcher = new IndexSearcher(reader);
 
+        context.terminateAfter(numDocs);
+        {
+            context.setSize(10);
+            TotalHitCountCollector collector = new TotalHitCountCollector();
+            context.queryCollectors().put(TotalHitCountCollector.class, collector);
+            QueryPhase.execute(context, contextSearcher, checkCancelled -> {});
+            assertFalse(context.queryResult().terminatedEarly());
+            assertThat(context.queryResult().topDocs().topDocs.totalHits.value, equalTo((long) numDocs));
+            assertThat(context.queryResult().topDocs().topDocs.scoreDocs.length, equalTo(10));
+            assertThat(collector.getTotalHits(), equalTo(numDocs));
+        }
+
+        context.terminateAfter(1);
         {
             context.setSize(1);
             QueryPhase.execute(context, contextSearcher, checkCancelled -> {});
@@ -419,7 +431,6 @@ public class QueryPhaseTests extends IndexShardTestCase {
             assertThat(context.queryResult().topDocs().topDocs.scoreDocs.length, equalTo(0));
             assertThat(collector.getTotalHits(), equalTo(1));
         }
-
         reader.close();
         dir.close();
     }

+ 1 - 1
server/src/test/java/org/elasticsearch/search/simple/SimpleSearchIT.java

@@ -250,7 +250,7 @@ public class SimpleSearchIT extends ESIntegTestCase {
                 .setTerminateAfter(2 * max).get();
 
         assertHitCount(searchResponse, max);
-        assertNull(searchResponse.isTerminatedEarly());
+        assertFalse(searchResponse.isTerminatedEarly());
     }
 
     public void testSimpleIndexSortEarlyTerminate() throws Exception {