diff --git a/solr/core/src/java/org/apache/solr/search/facet/FacetProcessor.java b/solr/core/src/java/org/apache/solr/search/facet/FacetProcessor.java index d5a4e23bb08..27cdaec1ec2 100644 --- a/solr/core/src/java/org/apache/solr/search/facet/FacetProcessor.java +++ b/solr/core/src/java/org/apache/solr/search/facet/FacetProcessor.java @@ -312,7 +312,7 @@ public abstract class FacetProcessor { } // note: only called by enum/stream prior to collect - void resetStats() { + void resetStats() throws IOException { countAcc.reset(); for (SlotAcc acc : accs) { acc.reset(); diff --git a/solr/core/src/java/org/apache/solr/search/facet/HLLAgg.java b/solr/core/src/java/org/apache/solr/search/facet/HLLAgg.java index 28c95e86e96..80e2bc1fb1a 100644 --- a/solr/core/src/java/org/apache/solr/search/facet/HLLAgg.java +++ b/solr/core/src/java/org/apache/solr/search/facet/HLLAgg.java @@ -52,16 +52,16 @@ public class HLLAgg extends StrAggValueSource { SchemaField sf = fcontext.qcontext.searcher().getSchema().getField(getArg()); if (sf.multiValued() || sf.getType().multiValuedFieldCache()) { if (sf.hasDocValues()) { - return new UniqueMultiDvSlotAcc(fcontext, getArg(), numSlots, fcontext.isShard() ? factory : null); + return new UniqueMultiDvSlotAcc(fcontext, sf, numSlots, fcontext.isShard() ? factory : null); } else { - return new UniqueMultivaluedSlotAcc(fcontext, getArg(), numSlots, fcontext.isShard() ? factory : null); + return new UniqueMultivaluedSlotAcc(fcontext, sf, numSlots, fcontext.isShard() ? factory : null); } } else { if (sf.getType().getNumberType() != null) { // always use hll here since we don't know how many values there are? return new NumericAcc(fcontext, getArg(), numSlots); } else { - return new UniqueSinglevaluedSlotAcc(fcontext, getArg(), numSlots, fcontext.isShard() ? factory : null); + return new UniqueSinglevaluedSlotAcc(fcontext, sf, numSlots, fcontext.isShard() ? factory : null); } } } diff --git a/solr/core/src/java/org/apache/solr/search/facet/SlotAcc.java b/solr/core/src/java/org/apache/solr/search/facet/SlotAcc.java index 1d8aecb2e5f..f5cdf82f445 100644 --- a/solr/core/src/java/org/apache/solr/search/facet/SlotAcc.java +++ b/solr/core/src/java/org/apache/solr/search/facet/SlotAcc.java @@ -94,7 +94,7 @@ public abstract class SlotAcc implements Closeable { } } - public abstract void reset(); + public abstract void reset() throws IOException; public abstract void resize(Resizer resizer); diff --git a/solr/core/src/java/org/apache/solr/search/facet/UniqueAgg.java b/solr/core/src/java/org/apache/solr/search/facet/UniqueAgg.java index 4cdfe02b5a5..4775e5fc8fe 100644 --- a/solr/core/src/java/org/apache/solr/search/facet/UniqueAgg.java +++ b/solr/core/src/java/org/apache/solr/search/facet/UniqueAgg.java @@ -43,15 +43,15 @@ public class UniqueAgg extends StrAggValueSource { SchemaField sf = fcontext.qcontext.searcher().getSchema().getField(getArg()); if (sf.multiValued() || sf.getType().multiValuedFieldCache()) { if (sf.hasDocValues()) { - return new UniqueMultiDvSlotAcc(fcontext, getArg(), numSlots, null); + return new UniqueMultiDvSlotAcc(fcontext, sf, numSlots, null); } else { - return new UniqueMultivaluedSlotAcc(fcontext, getArg(), numSlots, null); + return new UniqueMultivaluedSlotAcc(fcontext, sf, numSlots, null); } } else { if (sf.getType().getNumberType() != null) { return new NumericAcc(fcontext, getArg(), numSlots); } else { - return new UniqueSinglevaluedSlotAcc(fcontext, getArg(), numSlots, null); + return new UniqueSinglevaluedSlotAcc(fcontext, sf, numSlots, null); } } } diff --git a/solr/core/src/java/org/apache/solr/search/facet/UniqueMultiDvSlotAcc.java b/solr/core/src/java/org/apache/solr/search/facet/UniqueMultiDvSlotAcc.java index 72a88ca4c64..65fa81ac6ab 100644 --- a/solr/core/src/java/org/apache/solr/search/facet/UniqueMultiDvSlotAcc.java +++ b/solr/core/src/java/org/apache/solr/search/facet/UniqueMultiDvSlotAcc.java @@ -25,19 +25,23 @@ import org.apache.lucene.index.SortedSetDocValues; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.FixedBitSet; import org.apache.lucene.util.LongValues; -import org.apache.solr.search.SolrIndexSearcher; +import org.apache.solr.schema.SchemaField; class UniqueMultiDvSlotAcc extends UniqueSlotAcc { - final SortedSetDocValues topLevel; - final SortedSetDocValues[] subDvs; - final MultiDocValues.OrdinalMap ordMap; + SortedSetDocValues topLevel; + SortedSetDocValues[] subDvs; + MultiDocValues.OrdinalMap ordMap; LongValues toGlobal; SortedSetDocValues subDv; - public UniqueMultiDvSlotAcc(FacetContext fcontext, String field, int numSlots, HLLAgg.HLLFactory factory) throws IOException { + public UniqueMultiDvSlotAcc(FacetContext fcontext, SchemaField field, int numSlots, HLLAgg.HLLFactory factory) throws IOException { super(fcontext, field, numSlots, factory); - SolrIndexSearcher searcher = fcontext.qcontext.searcher(); - topLevel = FieldUtil.getSortedSetDocValues(fcontext.qcontext, searcher.getSchema().getField(field), null); + } + + @Override + public void reset() throws IOException { + super.reset(); + topLevel = FieldUtil.getSortedSetDocValues(fcontext.qcontext, field, null); nTerms = (int) topLevel.getValueCount(); if (topLevel instanceof MultiDocValues.MultiSortedSetDocValues) { ordMap = ((MultiDocValues.MultiSortedSetDocValues) topLevel).mapping; @@ -55,6 +59,9 @@ class UniqueMultiDvSlotAcc extends UniqueSlotAcc { @Override public void setNextReader(LeafReaderContext readerContext) throws IOException { + if (topLevel == null) { + reset(); + } super.setNextReader(readerContext); if (subDvs != null) { subDv = subDvs[readerContext.ord]; diff --git a/solr/core/src/java/org/apache/solr/search/facet/UniqueMultivaluedSlotAcc.java b/solr/core/src/java/org/apache/solr/search/facet/UniqueMultivaluedSlotAcc.java index 56a498e4389..10adcf06dd2 100644 --- a/solr/core/src/java/org/apache/solr/search/facet/UniqueMultivaluedSlotAcc.java +++ b/solr/core/src/java/org/apache/solr/search/facet/UniqueMultivaluedSlotAcc.java @@ -21,16 +21,17 @@ import java.io.IOException; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.FixedBitSet; +import org.apache.solr.schema.SchemaField; import org.apache.solr.search.SolrIndexSearcher; class UniqueMultivaluedSlotAcc extends UniqueSlotAcc implements UnInvertedField.Callback { private UnInvertedField uif; private UnInvertedField.DocToTerm docToTerm; - public UniqueMultivaluedSlotAcc(FacetContext fcontext, String field, int numSlots, HLLAgg.HLLFactory factory) throws IOException { + public UniqueMultivaluedSlotAcc(FacetContext fcontext, SchemaField field, int numSlots, HLLAgg.HLLFactory factory) throws IOException { super(fcontext, field, numSlots, factory); SolrIndexSearcher searcher = fcontext.qcontext.searcher(); - uif = UnInvertedField.getUnInvertedField(field, searcher); + uif = UnInvertedField.getUnInvertedField(field.getName(), searcher); docToTerm = uif.new DocToTerm(); fcontext.qcontext.addCloseHook(this); // TODO: find way to close accumulators instead of using close hook? nTerms = uif.numTerms(); diff --git a/solr/core/src/java/org/apache/solr/search/facet/UniqueSinglevaluedSlotAcc.java b/solr/core/src/java/org/apache/solr/search/facet/UniqueSinglevaluedSlotAcc.java index e0a1852399f..b39f2823453 100644 --- a/solr/core/src/java/org/apache/solr/search/facet/UniqueSinglevaluedSlotAcc.java +++ b/solr/core/src/java/org/apache/solr/search/facet/UniqueSinglevaluedSlotAcc.java @@ -25,19 +25,26 @@ import org.apache.lucene.index.SortedDocValues; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.FixedBitSet; import org.apache.lucene.util.LongValues; +import org.apache.solr.schema.SchemaField; import org.apache.solr.search.SolrIndexSearcher; class UniqueSinglevaluedSlotAcc extends UniqueSlotAcc { - final SortedDocValues topLevel; - final SortedDocValues[] subDvs; - final MultiDocValues.OrdinalMap ordMap; + SortedDocValues topLevel; + SortedDocValues[] subDvs; + MultiDocValues.OrdinalMap ordMap; LongValues toGlobal; SortedDocValues subDv; - public UniqueSinglevaluedSlotAcc(FacetContext fcontext, String field, int numSlots, HLLAgg.HLLFactory factory) throws IOException { + public UniqueSinglevaluedSlotAcc(FacetContext fcontext, SchemaField field, int numSlots, HLLAgg.HLLFactory factory) throws IOException { super(fcontext, field, numSlots, factory); + // let setNextReader lazily call reset(), that way an extra call to reset() after creation won't matter + } + + @Override + public void reset() throws IOException { + super.reset(); SolrIndexSearcher searcher = fcontext.qcontext.searcher(); - topLevel = FieldUtil.getSortedDocValues(fcontext.qcontext, searcher.getSchema().getField(field), null); + topLevel = FieldUtil.getSortedDocValues(fcontext.qcontext, field, null); nTerms = topLevel.getValueCount(); if (topLevel instanceof MultiDocValues.MultiSortedDocValues) { ordMap = ((MultiDocValues.MultiSortedDocValues)topLevel).mapping; @@ -55,6 +62,9 @@ class UniqueSinglevaluedSlotAcc extends UniqueSlotAcc { @Override public void setNextReader(LeafReaderContext readerContext) throws IOException { + if (topLevel == null) { + reset(); + } super.setNextReader(readerContext); if (subDvs != null) { subDv = subDvs[readerContext.ord]; diff --git a/solr/core/src/java/org/apache/solr/search/facet/UniqueSlotAcc.java b/solr/core/src/java/org/apache/solr/search/facet/UniqueSlotAcc.java index ae542ac5e7f..607b0674b79 100644 --- a/solr/core/src/java/org/apache/solr/search/facet/UniqueSlotAcc.java +++ b/solr/core/src/java/org/apache/solr/search/facet/UniqueSlotAcc.java @@ -37,15 +37,15 @@ abstract class UniqueSlotAcc extends SlotAcc { int[] counts; // populated with the cardinality once int nTerms; - public UniqueSlotAcc(FacetContext fcontext, String field, int numSlots, HLLAgg.HLLFactory factory) throws IOException { + public UniqueSlotAcc(FacetContext fcontext, SchemaField field, int numSlots, HLLAgg.HLLFactory factory) throws IOException { super(fcontext); this.factory = factory; arr = new FixedBitSet[numSlots]; - this.field = fcontext.searcher.getSchema().getField(field); + this.field = field; } @Override - public void reset() { + public void reset() throws IOException { counts = null; for (FixedBitSet bits : arr) { if (bits == null) continue; diff --git a/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java b/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java index 3f31cca5bc3..4fcee671e14 100644 --- a/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java +++ b/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java @@ -1360,6 +1360,15 @@ public class TestJsonFacets extends SolrTestCaseHS { "}" ); + // test acc reuse (i.e. reset() method). This is normally used for stats that are not calculated in the first phase, + // currently non-sorting stats. + client.testJQ(params(p, "q", "*:*" + , "json.facet", "{f1:{type:terms, field:'${cat_s}', facet:{h:'hll(${where_s})'} }}" + ) + , "facets=={ 'count':6, " + + "'f1':{ buckets:[{val:B, count:3, h:2},{val:A, count:2, h:2}] } } " + ); + } @Test