| 
15 | 15 | import org.apache.lucene.index.IndexReader;  | 
16 | 16 | import org.apache.lucene.index.LeafReaderContext;  | 
17 | 17 | import org.apache.lucene.index.Term;  | 
 | 18 | +import org.apache.lucene.search.BulkScorer;  | 
 | 19 | +import org.apache.lucene.search.CollectionTerminatedException;  | 
18 | 20 | import org.apache.lucene.search.CollectorManager;  | 
 | 21 | +import org.apache.lucene.search.DocIdSetIterator;  | 
19 | 22 | import org.apache.lucene.search.FilterLeafCollector;  | 
20 | 23 | import org.apache.lucene.search.IndexSearcher;  | 
21 | 24 | import org.apache.lucene.search.LeafCollector;  | 
22 | 25 | import org.apache.lucene.search.MatchAllDocsQuery;  | 
23 | 26 | import org.apache.lucene.search.Query;  | 
24 | 27 | import org.apache.lucene.search.ScoreMode;  | 
 | 28 | +import org.apache.lucene.search.Weight;  | 
25 | 29 | import org.apache.lucene.store.Directory;  | 
26 | 30 | import org.apache.lucene.tests.index.RandomIndexWriter;  | 
27 | 31 | import org.elasticsearch.test.ESTestCase;  | 
@@ -121,15 +125,40 @@ public void testHitCountFromWeightDoesNotEarlyTerminate() throws IOException {  | 
121 | 125 | 
 
  | 
122 | 126 |     public void testCollectedHitCount() throws Exception {  | 
123 | 127 |         Query query = new NonCountingTermQuery(new Term("string", "a1"));  | 
124 |  | -        int threshold = randomIntBetween(1, 10000);  | 
125 |  | -        assumeTrue("bug with single collection & single segment: https://github.com/elastic/elasticsearch/issues/106647", threshold > 1);  | 
126 |  | -        // there's one doc matching the query: any totalHitsThreshold greater than or equal to 1 will not cause early termination  | 
 | 128 | +        int threshold = randomIntBetween(2, 10000);  | 
 | 129 | +        // there's one doc matching the query: any totalHitsThreshold greater than 1 will not cause early termination  | 
127 | 130 |         CollectorManager<PartialHitCountCollector, Result> collectorManager = createCollectorManager(new HitsThresholdChecker(threshold));  | 
128 | 131 |         Result result = searcher.search(query, collectorManager);  | 
129 | 132 |         assertEquals(1, result.totalHits);  | 
130 | 133 |         assertFalse(result.terminatedAfter);  | 
131 | 134 |     }  | 
132 | 135 | 
 
  | 
 | 136 | +    public void testThresholdOne() throws Exception {  | 
 | 137 | +        Query query = new NonCountingTermQuery(new Term("string", "a1"));  | 
 | 138 | +        Weight weight = query.createWeight(searcher, ScoreMode.COMPLETE, 0f);  | 
 | 139 | +        CollectorManager<PartialHitCountCollector, Result> collectorManager = createCollectorManager(new HitsThresholdChecker(1));  | 
 | 140 | +        // threshold 1 behaves differently depending on whether there is a single segment (no early termination) or multiple segments.  | 
 | 141 | +        // With inter-segment concurrency the behaviour is not deterministic and depends on the timing of the different threads.  | 
 | 142 | +        // Without inter-segment concurrency the behaviour depends on which segment holds the matching document.  | 
 | 143 | +        // This is because the check for early termination is performed every time a leaf collector is pulled for a segment, as well  | 
 | 144 | +        // as for every collected doc.  | 
 | 145 | +        PartialHitCountCollector partialHitCountCollector = collectorManager.newCollector();  | 
 | 146 | +        int i = 0;  | 
 | 147 | +        while (partialHitCountCollector.getTotalHits() == 0 && i < searcher.getLeafContexts().size()) {  | 
 | 148 | +            LeafReaderContext ctx = searcher.getLeafContexts().get(i++);  | 
 | 149 | +            LeafCollector leafCollector = partialHitCountCollector.getLeafCollector(ctx);  | 
 | 150 | +            BulkScorer bulkScorer = weight.bulkScorer(ctx);  | 
 | 151 | +            bulkScorer.score(leafCollector, ctx.reader().getLiveDocs(), 0, DocIdSetIterator.NO_MORE_DOCS);  | 
 | 152 | +        }  | 
 | 153 | +        assertEquals(1, partialHitCountCollector.getTotalHits());  | 
 | 154 | +        assertFalse(partialHitCountCollector.hasEarlyTerminated());  | 
 | 155 | +        expectThrows(  | 
 | 156 | +            CollectionTerminatedException.class,  | 
 | 157 | +            () -> partialHitCountCollector.getLeafCollector(randomFrom(searcher.getLeafContexts()))  | 
 | 158 | +        );  | 
 | 159 | +        assertTrue(partialHitCountCollector.hasEarlyTerminated());  | 
 | 160 | +    }  | 
 | 161 | + | 
133 | 162 |     public void testCollectedHitCountEarlyTerminated() throws Exception {  | 
134 | 163 |         Query query = new NonCountingTermQuery(new Term("string", "foo"));  | 
135 | 164 |         // there's three docs matching the query: any totalHitsThreshold lower than 3 will trigger early termination  | 
 | 
0 commit comments