diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 9ec2de39026..761d06db480 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -256,6 +256,11 @@ Optimizations * SOLR-11880: Avoid creating new exceptions for every request made to MDCAwareThreadPoolExecutor by distributed search and update operations. (Varun Thacker, shalin) +* SOLR-12375: Optimize Lucene ScoreMode use: + A non-cached filter query could be told incorrectly that scores were needed. + The /export (ExportQParserPlugin) would declare incorrectly that scores are needed. + Expanded docs (expand component) could be told incorrectly that scores are needed. (David Smiley) + Other Changes ---------------------- diff --git a/solr/core/src/java/org/apache/solr/handler/component/ExpandComponent.java b/solr/core/src/java/org/apache/solr/handler/component/ExpandComponent.java index 09b4b364335..f6e29e4e796 100644 --- a/solr/core/src/java/org/apache/solr/handler/component/ExpandComponent.java +++ b/solr/core/src/java/org/apache/solr/handler/component/ExpandComponent.java @@ -551,11 +551,6 @@ public class ExpandComponent extends SearchComponent implements PluginInfoInitia } } - @Override - public ScoreMode scoreMode() { - return ScoreMode.COMPLETE; // TODO: is this always true? - } - public LeafCollector getLeafCollector(LeafReaderContext context) throws IOException { final int docBase = context.docBase; @@ -634,11 +629,6 @@ public class ExpandComponent extends SearchComponent implements PluginInfoInitia this.field = field; this.collapsedSet = collapsedSet; } - - @Override - public ScoreMode scoreMode() { - return ScoreMode.COMPLETE; // TODO: is this always true? - } public LeafCollector getLeafCollector(LeafReaderContext context) throws IOException { final int docBase = context.docBase; @@ -683,8 +673,19 @@ public class ExpandComponent extends SearchComponent implements PluginInfoInitia } - private interface GroupCollector { + //TODO lets just do simple abstract base class -- a fine use of inheritance + private interface GroupCollector extends Collector { public LongObjectMap getGroups(); + + @Override + default ScoreMode scoreMode() { + final LongObjectMap groups = getGroups(); + if (groups.isEmpty()) { + return ScoreMode.COMPLETE; // doesn't matter? + } else { + return groups.iterator().next().value.scoreMode(); // we assume all the collectors should have the same nature + } + } } private Query getGroupQuery(String fname, diff --git a/solr/core/src/java/org/apache/solr/search/ExportQParserPlugin.java b/solr/core/src/java/org/apache/solr/search/ExportQParserPlugin.java index fd625aff158..dbaf3db56ca 100644 --- a/solr/core/src/java/org/apache/solr/search/ExportQParserPlugin.java +++ b/solr/core/src/java/org/apache/solr/search/ExportQParserPlugin.java @@ -16,19 +16,27 @@ */ package org.apache.solr.search; -import org.apache.lucene.util.FixedBitSet; -import org.apache.solr.handler.component.MergeStrategy; -import org.apache.solr.request.SolrRequestInfo; - -import org.apache.lucene.search.*; -import org.apache.lucene.index.*; -import org.apache.solr.request.SolrQueryRequest; -import org.apache.solr.common.params.SolrParams; - import java.io.IOException; import java.util.Map; import java.util.Objects; +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.LeafReaderContext; +import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.LeafCollector; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.ScoreDoc; +import org.apache.lucene.search.ScoreMode; +import org.apache.lucene.search.Scorer; +import org.apache.lucene.search.TopDocs; +import org.apache.lucene.search.TopDocsCollector; +import org.apache.lucene.search.Weight; +import org.apache.lucene.util.FixedBitSet; +import org.apache.solr.common.params.SolrParams; +import org.apache.solr.handler.component.MergeStrategy; +import org.apache.solr.request.SolrQueryRequest; +import org.apache.solr.request.SolrRequestInfo; + public class ExportQParserPlugin extends QParserPlugin { public static final String NAME = "xport"; @@ -73,7 +81,7 @@ public class ExportQParserPlugin extends QParserPlugin { @Override public Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException{ - return mainQuery.createWeight(searcher, ScoreMode.COMPLETE, boost); + return mainQuery.createWeight(searcher, scoreMode, boost); } public Query rewrite(IndexReader reader) throws IOException { @@ -177,7 +185,7 @@ public class ExportQParserPlugin extends QParserPlugin { @Override public ScoreMode scoreMode() { - return ScoreMode.COMPLETE; // TODO: is this the case? + return ScoreMode.COMPLETE_NO_SCORES; } } diff --git a/solr/core/src/java/org/apache/solr/search/ReRankCollector.java b/solr/core/src/java/org/apache/solr/search/ReRankCollector.java index 9b6ecb3d8b3..0447053b3cb 100644 --- a/solr/core/src/java/org/apache/solr/search/ReRankCollector.java +++ b/solr/core/src/java/org/apache/solr/search/ReRankCollector.java @@ -65,6 +65,7 @@ public class ReRankCollector extends TopDocsCollector { this.mainCollector = TopScoreDocCollector.create(Math.max(this.reRankDocs, length)); } else { sort = sort.rewrite(searcher); + //scores are needed for Rescorer (regardless of whether sort needs it) this.mainCollector = TopFieldCollector.create(sort, Math.max(this.reRankDocs, length), false, true, true, true); } this.searcher = searcher; @@ -82,7 +83,7 @@ public class ReRankCollector extends TopDocsCollector { @Override public ScoreMode scoreMode() { - return ScoreMode.COMPLETE; + return ScoreMode.COMPLETE; // since the scores will be needed by Rescorer as input regardless of mainCollector } public TopDocs topDocs(int start, int howMany) { diff --git a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java index 2dbc2db9b08..a8c168ed8fc 100644 --- a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java +++ b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java @@ -1061,7 +1061,7 @@ public class SolrIndexSearcher extends IndexSearcher implements Closeable, SolrI List weights = new ArrayList<>(notCached.size()); for (Query q : notCached) { Query qq = QueryUtils.makeQueryable(q); - weights.add(createWeight(rewrite(qq), ScoreMode.COMPLETE, 1)); + weights.add(createWeight(rewrite(qq), ScoreMode.COMPLETE_NO_SCORES, 1)); } pf.filter = new FilterImpl(answer, weights); pf.hasDeletedDocs = (answer == null); // if all clauses were uncached, the resulting filter may match deleted docs @@ -1672,7 +1672,7 @@ public class SolrIndexSearcher extends IndexSearcher implements Closeable, SolrI @Override public ScoreMode scoreMode() { - return ScoreMode.COMPLETE; + return ScoreMode.TOP_SCORES; } };