SOLR-7473: implement facet range mincount

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1676107 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yonik Seeley 2015-04-26 14:16:49 +00:00
parent 3862c52b58
commit 62ee80ad89
5 changed files with 30 additions and 7 deletions

View File

@ -119,6 +119,12 @@ New Features
"facet.range.method=filter") or DocValues ("facet.range.method=dv").
Input parameters and output of both methods are the same. (Tomás Fernández Löbbe)
* SOLR-7473: Facet Module (Json Facet API) range faceting now supports the "mincount"
parameter in range facets to supress buckets less than that count. The default
for "mincount" remains 0 for range faceting.
Example: prices:{ type:range, field:price, mincount:1, start:0, end:100, gap:10 }
(yonik)
Bug Fixes
----------------------

View File

@ -781,6 +781,7 @@ class FacetRangeMerger extends FacetBucketMerger<FacetRange> {
mergeBucketList(bucketList);
}
// TODO: share more merging with field faceting
public void mergeBucketList(List<SimpleOrderedMap> bucketList) {
for (SimpleOrderedMap bucketRes : bucketList) {
Comparable bucketVal = (Comparable)bucketRes.get("val");
@ -798,14 +799,11 @@ class FacetRangeMerger extends FacetBucketMerger<FacetRange> {
SimpleOrderedMap result = new SimpleOrderedMap(4);
List<SimpleOrderedMap> resultBuckets = new ArrayList<>(buckets.size());
// TODO: if we implement mincount for ranges, we'll need to sort buckets (see FacetFieldMerger)
for (FacetBucket bucket : buckets.values()) {
/***
if (bucket.getCount() < freq.mincount) {
continue;
continue;
}
***/
resultBuckets.add( bucket.getMergedBucket() );
}

View File

@ -23,9 +23,7 @@ import java.util.Date;
import java.util.EnumSet;
import java.util.List;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.FacetParams;
import org.apache.solr.common.util.SimpleOrderedMap;
@ -44,6 +42,8 @@ public class FacetRange extends FacetRequest {
boolean hardend = false;
EnumSet<FacetParams.FacetRangeInclude> include;
EnumSet<FacetParams.FacetRangeOther> others;
long mincount = 0;
@Override
public FacetProcessor createFacetProcessor(FacetContext fcontext) {
@ -62,6 +62,7 @@ class FacetRangeProcessor extends FacetProcessor<FacetRange> {
Calc calc;
List<Range> rangeList;
List<Range> otherList;
long effectiveMincount;
FacetRangeProcessor(FacetContext fcontext, FacetRange freq) {
super(fcontext, freq);
@ -69,8 +70,11 @@ class FacetRangeProcessor extends FacetProcessor<FacetRange> {
@Override
public void process() throws IOException {
sf = fcontext.searcher.getSchema().getField(freq.field);
// Under the normal mincount=0, each shard will need to return 0 counts since we don't calculate buckets at the top level.
// But if mincount>0 then our sub mincount can be set to 1.
effectiveMincount = fcontext.isShard() ? (freq.mincount > 0 ? 1 : 0) : freq.mincount;
sf = fcontext.searcher.getSchema().getField(freq.field);
response = getRangeCounts();
}
@ -236,6 +240,7 @@ class FacetRangeProcessor extends FacetProcessor<FacetRange> {
res.add("buckets", buckets);
for (int idx = 0; idx<rangeList.size(); idx++) {
if (effectiveMincount > 0 && countAcc.getCount(idx) < effectiveMincount) continue;
Range range = rangeList.get(idx);
SimpleOrderedMap bucket = new SimpleOrderedMap();
buckets.add(bucket);
@ -245,6 +250,7 @@ class FacetRangeProcessor extends FacetProcessor<FacetRange> {
}
for (int idx = 0; idx<otherList.size(); idx++) {
// we dont' skip these buckets based on mincount
Range range = otherList.get(idx);
SimpleOrderedMap bucket = new SimpleOrderedMap();
res.add(range.label.toString(), bucket);

View File

@ -686,6 +686,7 @@ class FacetRangeParser extends FacetParser<FacetRange> {
facet.end = m.get("end");
facet.gap = m.get("gap");
facet.hardend = getBoolean(m, "hardend", facet.hardend);
facet.mincount = getLong(m, "mincount", 0);
// TODO: refactor list-of-options code

View File

@ -690,6 +690,16 @@ public class TestJsonFacets extends SolrTestCaseHS {
" } }"
);
// range facet with mincount
client.testJQ(params(p, "q", "*:*"
, "json.facet", "{f:{type:range, field:${num_d}, start:-5, end:10, gap:5, other:all, mincount:2, facet:{ x:'sum(${num_i})', ny:{query:'${where_s}:NY'}} }}"
)
, "facets=={count:6, f:{buckets:[ {val:0.0,count:2,x:5.0,ny:{count:1}} ]" +
",before: {count:1,x:-5.0,ny:{count:0}}" +
",after: {count:1,x:7.0, ny:{count:0}}" +
",between:{count:3,x:0.0, ny:{count:2}}" +
" } }"
);
// range facet with sub facets and stats, with "other:all", on subset
client.testJQ(params(p, "q", "id:(3 4 6)"
@ -702,6 +712,8 @@ public class TestJsonFacets extends SolrTestCaseHS {
" } }"
);
// stats at top level
client.testJQ(params(p, "q", "*:*"
, "json.facet", "{ sum1:'sum(${num_d})', sumsq1:'sumsq(${num_d})', avg1:'avg(${num_d})', min1:'min(${num_d})', max1:'max(${num_d})', numwhere:'unique(${where_s})', unique_num_i:'unique(${num_i})', unique_num_d:'unique(${num_d})', unique_date:'unique(${date})', med:'percentile(${num_d},50)', perc:'percentile(${num_d},0,50.0,100)' }"