diff --git a/lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java b/lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java index 6842d2142366..a8f8d14c24f3 100644 --- a/lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java +++ b/lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java @@ -630,12 +630,45 @@ private TopFieldDocs searchAfter( */ public T search(Query query, CollectorManager collectorManager) throws IOException { - CollectorOwner collectorOwner = new CollectorOwner<>(collectorManager); - final C firstCollector = collectorOwner.newCollector(); + final C firstCollector = collectorManager.newCollector(); query = rewrite(query, firstCollector.scoreMode().needsScores()); final Weight weight = createWeight(query, firstCollector.scoreMode(), 1); - search(weight, collectorOwner, firstCollector); - return collectorOwner.getResult(); + return search(weight, collectorManager, firstCollector); + } + + private T search( + Weight weight, CollectorManager collectorManager, C firstCollector) throws IOException { + final LeafSlice[] leafSlices = getSlices(); + if (leafSlices.length == 0) { + // there are no segments, nothing to offload to the executor, but we do need to call reduce to + // create some kind of empty result + assert leafContexts.isEmpty(); + return collectorManager.reduce(Collections.singletonList(firstCollector)); + } else { + final List collectors = new ArrayList<>(leafSlices.length); + collectors.add(firstCollector); + final ScoreMode scoreMode = firstCollector.scoreMode(); + for (int i = 1; i < leafSlices.length; ++i) { + final C collector = collectorManager.newCollector(); + collectors.add(collector); + if (scoreMode != collector.scoreMode()) { + throw new IllegalStateException( + "CollectorManager does not always produce collectors with the same score mode"); + } + } + final List> listTasks = new ArrayList<>(leafSlices.length); + for (int i = 0; i < leafSlices.length; ++i) { + final LeafReaderContext[] leaves = leafSlices[i].leaves; + final C collector = collectors.get(i); + listTasks.add( + () -> { + search(Arrays.asList(leaves), weight, collector); + return collector; + }); + } + List results = taskExecutor.invokeAll(listTasks); + return collectorManager.reduce(results); + } } /**