diff --git a/solr/src/java/org/apache/solr/search/Grouping.java b/solr/src/java/org/apache/solr/search/Grouping.java index 21e9e1fd396..6c8a3dd9a17 100755 --- a/solr/src/java/org/apache/solr/search/Grouping.java +++ b/solr/src/java/org/apache/solr/search/Grouping.java @@ -143,6 +143,7 @@ class TopGroupCollector extends GroupCollector { int spareSlot; int matches; + boolean groupsFull = false; public TopGroupCollector(ValueSource groupByVS, Map vsContext, Sort sort, int nGroups) throws IOException { this.vs = groupByVS; @@ -173,6 +174,29 @@ class TopGroupCollector extends GroupCollector { @Override public void collect(int doc) throws IOException { matches++; + + // Doing this before ValueFiller and HashMap are executed + // This allows us to exit this method asap when a doc is not competitive + // As it turns out this happens most of the times. + if (groupsFull) { + for (int i = 0;; i++) { + final int c = reversed[i] * comparators[i].compareBottom(doc); + if (c < 0) { + // Definitely not competitive. So don't even bother to continue + return; + } else if (c > 0) { + // Definitely competitive. + break; + } else if (i == comparators.length - 1) { + // Here c=0. If we're at the last comparator, this doc is not + // competitive, since docs are visited in doc Id order, which means + // this doc cannot compete with any other document in the queue. + return; + } + } + } + + // These next two statements are expensive filler.fillValue(doc); SearchGroup group = groupMap.get(mval); if (group == null) { @@ -191,6 +215,7 @@ class TopGroupCollector extends GroupCollector { } if (orderedGroups == null) { + groupsFull = true; buildSet(); } diff --git a/solr/src/java/org/apache/solr/search/SolrIndexSearcher.java b/solr/src/java/org/apache/solr/search/SolrIndexSearcher.java index 869046ef7b8..3555d26c34b 100644 --- a/solr/src/java/org/apache/solr/search/SolrIndexSearcher.java +++ b/solr/src/java/org/apache/solr/search/SolrIndexSearcher.java @@ -17,32 +17,33 @@ package org.apache.solr.search; -import org.apache.lucene.document.*; +import org.apache.lucene.document.Document; +import org.apache.lucene.document.FieldSelector; +import org.apache.lucene.document.FieldSelectorResult; import org.apache.lucene.index.*; import org.apache.lucene.search.*; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import org.apache.lucene.util.Bits; import org.apache.lucene.util.BytesRef; +import org.apache.lucene.util.OpenBitSet; import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.SimpleOrderedMap; import org.apache.solr.core.SolrConfig; import org.apache.solr.core.SolrCore; import org.apache.solr.core.SolrInfoMBean; +import org.apache.solr.request.UnInvertedField; import org.apache.solr.schema.IndexSchema; import org.apache.solr.schema.SchemaField; -import org.apache.solr.request.UnInvertedField; -import org.apache.lucene.util.OpenBitSet; +import org.apache.solr.search.function.ValueSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.net.URL; import java.util.*; import java.util.concurrent.atomic.AtomicLong; -import org.apache.solr.search.function.ValueSource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** * SolrIndexSearcher adds schema awareness and caching functionality diff --git a/solr/src/java/org/apache/solr/search/function/DocValues.java b/solr/src/java/org/apache/solr/search/function/DocValues.java index da2e9cd4770..2510082720e 100644 --- a/solr/src/java/org/apache/solr/search/function/DocValues.java +++ b/solr/src/java/org/apache/solr/search/function/DocValues.java @@ -46,6 +46,18 @@ public abstract class DocValues { public double doubleVal(int doc) { throw new UnsupportedOperationException(); } // TODO: should we make a termVal, returns BytesRef? public String strVal(int doc) { throw new UnsupportedOperationException(); } + + /** + * @param doc The doc to retrieve to sort ordinal for + * @return the sort ordinal for the specified doc + * TODO: Maybe we can just use intVal for this... + */ + public int ordVal(int doc) { throw new UnsupportedOperationException(); } + + /** + * @return the number of unique sort ordinals this instance has + */ + public int numOrd() { throw new UnsupportedOperationException(); } public abstract String toString(int doc); /** @lucene.experimental */ diff --git a/solr/src/java/org/apache/solr/search/function/OrdFieldSource.java b/solr/src/java/org/apache/solr/search/function/OrdFieldSource.java index 8e2d417a581..b910f33b338 100644 --- a/solr/src/java/org/apache/solr/search/function/OrdFieldSource.java +++ b/solr/src/java/org/apache/solr/search/function/OrdFieldSource.java @@ -74,6 +74,14 @@ public class OrdFieldSource extends ValueSource { return (double)termsIndex.getOrd(doc); } + public int ordVal(int doc) { + return termsIndex.getOrd(doc); + } + + public int numOrd() { + return termsIndex.numOrd(); + } + public String strVal(int doc) { // the string value of the ordinal, not the string itself return Integer.toString(termsIndex.getOrd(doc)); diff --git a/solr/src/java/org/apache/solr/search/function/ReverseOrdFieldSource.java b/solr/src/java/org/apache/solr/search/function/ReverseOrdFieldSource.java index 36f17f7443a..ef595a59aae 100644 --- a/solr/src/java/org/apache/solr/search/function/ReverseOrdFieldSource.java +++ b/solr/src/java/org/apache/solr/search/function/ReverseOrdFieldSource.java @@ -73,6 +73,14 @@ public class ReverseOrdFieldSource extends ValueSource { return (long)(end - sindex.getOrd(doc)); } + public int ordVal(int doc) { + return (end - sindex.getOrd(doc)); + } + + public int numOrd() { + return end; + } + public double doubleVal(int doc) { return (double)(end - sindex.getOrd(doc)); }