SOLR-7495: Support Facet.field on a non-DocValued, single-value, int field

This commit is contained in:
Dennis Gove 2017-01-04 22:25:29 -05:00
parent bd39ae9c9d
commit f9e3554838
3 changed files with 33 additions and 18 deletions

View File

@ -327,6 +327,8 @@ Bug Fixes
* SOLR-9919: random Streaming Expression is not registered in /stream or /graph handler (Joel Bernstein)
* SOLR-7495: Support Facet.field on a non-DocValued, single-value, int field (Varun Thacker, Scott Stults)
Other Changes
----------------------

View File

@ -45,6 +45,7 @@ import org.apache.lucene.index.Terms;
import org.apache.lucene.index.TermsEnum;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Collector;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.FilterCollector;
import org.apache.lucene.search.LeafCollector;
@ -649,21 +650,10 @@ public class SimpleFacets {
BytesRef prefixBytesRef = prefix != null ? new BytesRef(prefix) : null;
final TermGroupFacetCollector collector = TermGroupFacetCollector.createTermGroupFacetCollector(groupField, field, multiToken, prefixBytesRef, 128);
SchemaField sf = searcher.getSchema().getFieldOrNull(groupField);
if (sf != null && sf.hasDocValues() == false && sf.multiValued() == false && sf.getType().getNumericType() != null) {
// it's a single-valued numeric field: we must currently create insanity :(
// there isn't a GroupedFacetCollector that works on numerics right now...
searcher.search(base.getTopFilter(), new FilterCollector(collector) {
@Override
public LeafCollector getLeafCollector(LeafReaderContext context) throws IOException {
LeafReader insane = Insanity.wrapInsanity(context.reader(), groupField);
return in.getLeafCollector(insane.getContext());
}
});
} else {
searcher.search(base.getTopFilter(), collector);
}
Collector groupWrapper = getInsanityWrapper(groupField, collector);
Collector fieldWrapper = getInsanityWrapper(field, groupWrapper);
// When GroupedFacetCollector can handle numerics we can remove the wrapped collectors
searcher.search(base.getTopFilter(), fieldWrapper);
boolean orderByCount = sort.equals(FacetParams.FACET_SORT_COUNT) || sort.equals(FacetParams.FACET_SORT_COUNT_LEGACY);
TermGroupFacetCollector.GroupedFacetResult result
@ -691,6 +681,23 @@ public class SimpleFacets {
return facetCounts;
}
private Collector getInsanityWrapper(final String field, Collector collector) {
SchemaField sf = searcher.getSchema().getFieldOrNull(field);
if (sf != null && !sf.hasDocValues() && !sf.multiValued() && sf.getType().getNumericType() != null) {
// it's a single-valued numeric field: we must currently create insanity :(
// there isn't a GroupedFacetCollector that works on numerics right now...
return new FilterCollector(collector) {
@Override
public LeafCollector getLeafCollector(LeafReaderContext context) throws IOException {
LeafReader insane = Insanity.wrapInsanity(context.reader(), field);
return in.getLeafCollector(insane.getContext());
}
};
} else {
return collector;
}
}
static final Executor directExecutor = new Executor() {

View File

@ -384,7 +384,7 @@ public class SimpleFacetsTest extends SolrTestCaseJ4 {
"*[count(//doc)=5]"
);
assertQ(
"Return two facet counts for field airport_a",
"Return two facet counts for field airport_a and duration_i1",
req(
"q", "*:*",
"fq", "id:[2000 TO 2004]",
@ -393,12 +393,18 @@ public class SimpleFacetsTest extends SolrTestCaseJ4 {
"group.field", "hotel_s1",
"facet", "true",
"facet.limit", facetLimit,
"facet.field", "airport_s1"
"facet.field", "airport_s1",
"facet.field", "duration_i1"
),
"//lst[@name='facet_fields']/lst[@name='airport_s1']",
"*[count(//lst[@name='airport_s1']/int)=2]",
"//lst[@name='airport_s1']/int[@name='ams'][.='2']",
"//lst[@name='airport_s1']/int[@name='dus'][.='1']"
"//lst[@name='airport_s1']/int[@name='dus'][.='1']",
"//lst[@name='facet_fields']/lst[@name='duration_i1']",
"*[count(//lst[@name='duration_i1']/int)=2]",
"//lst[@name='duration_i1']/int[@name='5'][.='2']",
"//lst[@name='duration_i1']/int[@name='10'][.='2']"
);
assertQ(
"Return one facet count for field airport_a using facet.offset",