Fix topDocs.totalHits assignment on scroll queries (#37180)
This change fixes an unreleased bug that assigns the wrong totalHits to scroll queries. Closes #37179
This commit is contained in:
parent
20c2c439e7
commit
054c3bb04f
|
@ -166,7 +166,6 @@ public class QueryPhase implements SearchPhase {
|
||||||
}
|
}
|
||||||
// ... and stop collecting after ${size} matches
|
// ... and stop collecting after ${size} matches
|
||||||
searchContext.terminateAfter(searchContext.size());
|
searchContext.terminateAfter(searchContext.size());
|
||||||
searchContext.trackTotalHitsUpTo(SearchContext.TRACK_TOTAL_HITS_DISABLED);
|
|
||||||
} else if (canEarlyTerminate(reader, searchContext.sort())) {
|
} else if (canEarlyTerminate(reader, searchContext.sort())) {
|
||||||
// now this gets interesting: since the search sort is a prefix of the index sort, we can directly
|
// now this gets interesting: since the search sort is a prefix of the index sort, we can directly
|
||||||
// skip to the desired doc
|
// skip to the desired doc
|
||||||
|
@ -177,7 +176,6 @@ public class QueryPhase implements SearchPhase {
|
||||||
.build();
|
.build();
|
||||||
query = bq;
|
query = bq;
|
||||||
}
|
}
|
||||||
searchContext.trackTotalHitsUpTo(SearchContext.TRACK_TOTAL_HITS_DISABLED);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -217,8 +217,6 @@ abstract class TopDocsCollectorContext extends QueryCollectorContext {
|
||||||
super(REASON_SEARCH_TOP_HITS, numHits);
|
super(REASON_SEARCH_TOP_HITS, numHits);
|
||||||
this.sortAndFormats = sortAndFormats;
|
this.sortAndFormats = sortAndFormats;
|
||||||
|
|
||||||
// implicit total hit counts are valid only when there is no filter collector in the chain
|
|
||||||
final int hitCount = hasFilterCollector ? -1 : shortcutTotalHitCount(reader, query);
|
|
||||||
final TopDocsCollector<?> topDocsCollector;
|
final TopDocsCollector<?> topDocsCollector;
|
||||||
if (trackTotalHitsUpTo == SearchContext.TRACK_TOTAL_HITS_DISABLED) {
|
if (trackTotalHitsUpTo == SearchContext.TRACK_TOTAL_HITS_DISABLED) {
|
||||||
// don't compute hit counts via the collector
|
// don't compute hit counts via the collector
|
||||||
|
@ -226,6 +224,8 @@ abstract class TopDocsCollectorContext extends QueryCollectorContext {
|
||||||
topDocsSupplier = new CachedSupplier<>(topDocsCollector::topDocs);
|
topDocsSupplier = new CachedSupplier<>(topDocsCollector::topDocs);
|
||||||
totalHitsSupplier = () -> new TotalHits(0, TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO);
|
totalHitsSupplier = () -> new TotalHits(0, TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO);
|
||||||
} else {
|
} else {
|
||||||
|
// implicit total hit counts are valid only when there is no filter collector in the chain
|
||||||
|
final int hitCount = hasFilterCollector ? -1 : shortcutTotalHitCount(reader, query);
|
||||||
if (hitCount == -1) {
|
if (hitCount == -1) {
|
||||||
topDocsCollector = createCollector(sortAndFormats, numHits, searchAfter, trackTotalHitsUpTo);
|
topDocsCollector = createCollector(sortAndFormats, numHits, searchAfter, trackTotalHitsUpTo);
|
||||||
topDocsSupplier = new CachedSupplier<>(topDocsCollector::topDocs);
|
topDocsSupplier = new CachedSupplier<>(topDocsCollector::topDocs);
|
||||||
|
@ -293,12 +293,11 @@ abstract class TopDocsCollectorContext extends QueryCollectorContext {
|
||||||
@Override
|
@Override
|
||||||
void postProcess(QuerySearchResult result) throws IOException {
|
void postProcess(QuerySearchResult result) throws IOException {
|
||||||
final TopDocs topDocs = topDocsSupplier.get();
|
final TopDocs topDocs = topDocsSupplier.get();
|
||||||
topDocs.totalHits = totalHitsSupplier.get();
|
final float maxScore;
|
||||||
float maxScore = maxScoreSupplier.get();
|
|
||||||
if (scrollContext.totalHits == null) {
|
if (scrollContext.totalHits == null) {
|
||||||
// first round
|
// first round
|
||||||
scrollContext.totalHits = topDocs.totalHits;
|
topDocs.totalHits = scrollContext.totalHits = totalHitsSupplier.get();
|
||||||
scrollContext.maxScore = maxScore;
|
maxScore = scrollContext.maxScore = maxScoreSupplier.get();
|
||||||
} else {
|
} else {
|
||||||
// subsequent round: the total number of hits and
|
// subsequent round: the total number of hits and
|
||||||
// the maximum score were computed on the first round
|
// the maximum score were computed on the first round
|
||||||
|
@ -367,7 +366,7 @@ abstract class TopDocsCollectorContext extends QueryCollectorContext {
|
||||||
// we can disable the tracking of total hits after the initial scroll query
|
// we can disable the tracking of total hits after the initial scroll query
|
||||||
// since the total hits is preserved in the scroll context.
|
// since the total hits is preserved in the scroll context.
|
||||||
int trackTotalHitsUpTo = searchContext.scrollContext().totalHits != null ?
|
int trackTotalHitsUpTo = searchContext.scrollContext().totalHits != null ?
|
||||||
SearchContext.TRACK_TOTAL_HITS_DISABLED : searchContext.trackTotalHitsUpTo();
|
SearchContext.TRACK_TOTAL_HITS_DISABLED : SearchContext.TRACK_TOTAL_HITS_ACCURATE;
|
||||||
// no matter what the value of from is
|
// no matter what the value of from is
|
||||||
int numDocs = Math.min(searchContext.size(), totalNumDocs);
|
int numDocs = Math.min(searchContext.size(), totalNumDocs);
|
||||||
return new ScrollingTopDocsCollectorContext(reader, query, searchContext.scrollContext(),
|
return new ScrollingTopDocsCollectorContext(reader, query, searchContext.scrollContext(),
|
||||||
|
|
|
@ -178,7 +178,6 @@ public class SearchStatsIT extends ESIntegTestCase {
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@AwaitsFix(bugUrl="https://github.com/elastic/elasticsearch/issues/37179")
|
|
||||||
public void testOpenContexts() {
|
public void testOpenContexts() {
|
||||||
String index = "test1";
|
String index = "test1";
|
||||||
createIndex(index);
|
createIndex(index);
|
||||||
|
|
Loading…
Reference in New Issue