You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by er...@apache.org on 2014/07/24 00:02:17 UTC
svn commit: r1612958 - in /lucene/dev/branches/branch_4x: ./ solr/
solr/core/ solr/core/src/java/org/apache/solr/handler/component/
solr/core/src/java/org/apache/solr/request/
solr/core/src/test-files/solr/collection1/conf/
solr/core/src/test/org/apach...
Author: erick
Date: Wed Jul 23 22:02:16 2014
New Revision: 1612958
URL: http://svn.apache.org/r1612958
Log:
SOLR-6216: Better faceting for multiple intervals on DV fields. Thanks Tomas
Added:
lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/request/IntervalFacets.java
- copied unchanged from r1612889, lucene/dev/trunk/solr/core/src/java/org/apache/solr/request/IntervalFacets.java
lucene/dev/branches/branch_4x/solr/core/src/test-files/solr/collection1/conf/schema-distrib-interval-faceting.xml
- copied unchanged from r1612889, lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema-distrib-interval-faceting.xml
lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/DistributedIntervalFacetingTest.java
- copied, changed from r1612889, lucene/dev/trunk/solr/core/src/test/org/apache/solr/DistributedIntervalFacetingTest.java
lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/request/TestIntervalFaceting.java
- copied, changed from r1612889, lucene/dev/trunk/solr/core/src/test/org/apache/solr/request/TestIntervalFaceting.java
Modified:
lucene/dev/branches/branch_4x/ (props changed)
lucene/dev/branches/branch_4x/solr/ (props changed)
lucene/dev/branches/branch_4x/solr/CHANGES.txt (contents, props changed)
lucene/dev/branches/branch_4x/solr/core/ (props changed)
lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java
lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/request/SimpleFacets.java
lucene/dev/branches/branch_4x/solr/core/src/test-files/solr/collection1/conf/schema-docValuesFaceting.xml
lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/TestGroupingSearch.java
lucene/dev/branches/branch_4x/solr/solrj/ (props changed)
lucene/dev/branches/branch_4x/solr/solrj/src/java/org/apache/solr/common/params/FacetParams.java
lucene/dev/branches/branch_4x/solr/test-framework/ (props changed)
lucene/dev/branches/branch_4x/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
Modified: lucene/dev/branches/branch_4x/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/CHANGES.txt?rev=1612958&r1=1612957&r2=1612958&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/solr/CHANGES.txt (original)
+++ lucene/dev/branches/branch_4x/solr/CHANGES.txt Wed Jul 23 22:02:16 2014
@@ -88,6 +88,9 @@ New Features
* SOLR-6263: Add DIH handler name to variable resolver as ${dih.handlerName}. (ehatcher)
+* SOLR-6216: Better faceting for multiple intervals on DV fields (Tomas Fernandez-Lobbe
+ via Erick Erickson)
+
Bug Fixes
----------------------
Modified: lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java?rev=1612958&r1=1612957&r2=1612958&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java (original)
+++ lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java Wed Jul 23 22:02:16 2014
@@ -23,6 +23,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -326,92 +327,16 @@ public class FacetComponent extends Sear
}
// Distributed facet_dates
- //
- // The implementation below uses the first encountered shard's
- // facet_dates as the basis for subsequent shards' data to be merged.
- // (the "NOW" param should ensure consistency)
- @SuppressWarnings("unchecked")
- SimpleOrderedMap<SimpleOrderedMap<Object>> facet_dates =
- (SimpleOrderedMap<SimpleOrderedMap<Object>>)
- facet_counts.get("facet_dates");
-
- if (facet_dates != null) {
+ doDistribDates(fi, facet_counts);
- // go through each facet_date
- for (Map.Entry<String,SimpleOrderedMap<Object>> entry : facet_dates) {
- final String field = entry.getKey();
- if (fi.dateFacets.get(field) == null) {
- // first time we've seen this field, no merging
- fi.dateFacets.add(field, entry.getValue());
-
- } else {
- // not the first time, merge current field
-
- SimpleOrderedMap<Object> shardFieldValues
- = entry.getValue();
- SimpleOrderedMap<Object> existFieldValues
- = fi.dateFacets.get(field);
-
- for (Map.Entry<String,Object> existPair : existFieldValues) {
- final String key = existPair.getKey();
- if (key.equals("gap") ||
- key.equals("end") ||
- key.equals("start")) {
- // we can skip these, must all be the same across shards
- continue;
- }
- // can be null if inconsistencies in shards responses
- Integer newValue = (Integer) shardFieldValues.get(key);
- if (null != newValue) {
- Integer oldValue = ((Integer) existPair.getValue());
- existPair.setValue(oldValue + newValue);
- }
- }
- }
- }
- }
// Distributed facet_ranges
- //
- // The implementation below uses the first encountered shard's
- // facet_ranges as the basis for subsequent shards' data to be merged.
- @SuppressWarnings("unchecked")
- SimpleOrderedMap<SimpleOrderedMap<Object>> facet_ranges =
- (SimpleOrderedMap<SimpleOrderedMap<Object>>)
- facet_counts.get("facet_ranges");
-
- if (facet_ranges != null) {
+ doDistribRanges(fi, facet_counts);
+
+
+ // Distributed facet_intervals
+ doDistribIntervals(fi, facet_counts);
- // go through each facet_range
- for (Map.Entry<String,SimpleOrderedMap<Object>> entry : facet_ranges) {
- final String field = entry.getKey();
- if (fi.rangeFacets.get(field) == null) {
- // first time we've seen this field, no merging
- fi.rangeFacets.add(field, entry.getValue());
-
- } else {
- // not the first time, merge current field counts
-
- @SuppressWarnings("unchecked")
- NamedList<Integer> shardFieldValues
- = (NamedList<Integer>) entry.getValue().get("counts");
-
- @SuppressWarnings("unchecked")
- NamedList<Integer> existFieldValues
- = (NamedList<Integer>) fi.rangeFacets.get(field).get("counts");
-
- for (Map.Entry<String,Integer> existPair : existFieldValues) {
- final String key = existPair.getKey();
- // can be null if inconsistencies in shards responses
- Integer newValue = shardFieldValues.get(key);
- if (null != newValue) {
- Integer oldValue = existPair.getValue();
- existPair.setValue(oldValue + newValue);
- }
- }
- }
- }
- }
}
//
@@ -480,6 +405,145 @@ public class FacetComponent extends Sear
}
}
+ //
+ // The implementation below uses the first encountered shard's
+ // facet_intervals as the basis for subsequent shards' data to be merged.
+ private void doDistribIntervals(FacetInfo fi, NamedList facet_counts) {
+ @SuppressWarnings("unchecked")
+ SimpleOrderedMap<SimpleOrderedMap<Integer>> facet_intervals =
+ (SimpleOrderedMap<SimpleOrderedMap<Integer>>)
+ facet_counts.get("facet_intervals");
+
+ if (facet_intervals != null) {
+
+ for (Map.Entry<String, SimpleOrderedMap<Integer>> entry : facet_intervals) {
+ final String field = entry.getKey();
+ SimpleOrderedMap<Integer> existingCounts = fi.intervalFacets.get(field);
+ if (existingCounts == null) {
+ // first time we've seen this field, no merging
+ fi.intervalFacets.add(field, entry.getValue());
+
+ } else {
+ // not the first time, merge current field counts
+ Iterator<Map.Entry<String, Integer>> newItr = entry.getValue().iterator();
+ Iterator<Map.Entry<String, Integer>> exItr = existingCounts.iterator();
+
+ // all intervals should be returned by each shard, even if they have zero count,
+ // and in the same order
+ while (exItr.hasNext()) {
+ Map.Entry<String, Integer> exItem = exItr.next();
+ if (!newItr.hasNext()) {
+ throw new SolrException(ErrorCode.SERVER_ERROR,
+ "Interval facet shard response missing key: " + exItem.getKey());
+ }
+ Map.Entry<String, Integer> newItem = newItr.next();
+ if (!newItem.getKey().equals(exItem.getKey())) {
+ throw new SolrException(ErrorCode.SERVER_ERROR,
+ "Interval facet shard response has extra key: " + newItem.getKey());
+ }
+ exItem.setValue(exItem.getValue() + newItem.getValue());
+ }
+ if (newItr.hasNext()) {
+ throw new SolrException(ErrorCode.SERVER_ERROR,
+ "Interval facet shard response has at least one extra key: "
+ + newItr.next().getKey());
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // The implementation below uses the first encountered shard's
+ // facet_ranges as the basis for subsequent shards' data to be merged.
+
+ private void doDistribRanges(FacetInfo fi, NamedList facet_counts) {
+ @SuppressWarnings("unchecked")
+ SimpleOrderedMap<SimpleOrderedMap<Object>> facet_ranges =
+ (SimpleOrderedMap<SimpleOrderedMap<Object>>)
+ facet_counts.get("facet_ranges");
+
+ if (facet_ranges != null) {
+
+ // go through each facet_range
+ for (Map.Entry<String,SimpleOrderedMap<Object>> entry : facet_ranges) {
+ final String field = entry.getKey();
+ if (fi.rangeFacets.get(field) == null) {
+ // first time we've seen this field, no merging
+ fi.rangeFacets.add(field, entry.getValue());
+
+ } else {
+ // not the first time, merge current field counts
+
+ @SuppressWarnings("unchecked")
+ NamedList<Integer> shardFieldValues
+ = (NamedList<Integer>) entry.getValue().get("counts");
+
+ @SuppressWarnings("unchecked")
+ NamedList<Integer> existFieldValues
+ = (NamedList<Integer>) fi.rangeFacets.get(field).get("counts");
+
+ for (Map.Entry<String,Integer> existPair : existFieldValues) {
+ final String key = existPair.getKey();
+ // can be null if inconsistencies in shards responses
+ Integer newValue = shardFieldValues.get(key);
+ if (null != newValue) {
+ Integer oldValue = existPair.getValue();
+ existPair.setValue(oldValue + newValue);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // The implementation below uses the first encountered shard's
+ // facet_dates as the basis for subsequent shards' data to be merged.
+ // (the "NOW" param should ensure consistency)
+ private void doDistribDates(FacetInfo fi, NamedList facet_counts) {
+ @SuppressWarnings("unchecked")
+ SimpleOrderedMap<SimpleOrderedMap<Object>> facet_dates =
+ (SimpleOrderedMap<SimpleOrderedMap<Object>>)
+ facet_counts.get("facet_dates");
+
+ if (facet_dates != null) {
+
+ // go through each facet_date
+ for (Map.Entry<String,SimpleOrderedMap<Object>> entry : facet_dates) {
+ final String field = entry.getKey();
+ if (fi.dateFacets.get(field) == null) {
+ // first time we've seen this field, no merging
+ fi.dateFacets.add(field, entry.getValue());
+
+ } else {
+ // not the first time, merge current field
+
+ SimpleOrderedMap<Object> shardFieldValues
+ = entry.getValue();
+ SimpleOrderedMap<Object> existFieldValues
+ = fi.dateFacets.get(field);
+
+ for (Map.Entry<String,Object> existPair : existFieldValues) {
+ final String key = existPair.getKey();
+ if (key.equals("gap") ||
+ key.equals("end") ||
+ key.equals("start")) {
+ // we can skip these, must all be the same across shards
+ continue;
+ }
+ // can be null if inconsistencies in shards responses
+ Integer newValue = (Integer) shardFieldValues.get(key);
+ if (null != newValue) {
+ Integer oldValue = ((Integer) existPair.getValue());
+ existPair.setValue(oldValue + newValue);
+ }
+ }
+ }
+ }
+ }
+ }
+
private void refineFacets(ResponseBuilder rb, ShardRequest sreq) {
FacetInfo fi = rb._facetInfo;
@@ -589,6 +653,7 @@ public class FacetComponent extends Sear
facet_counts.add("facet_dates", fi.dateFacets);
facet_counts.add("facet_ranges", fi.rangeFacets);
+ facet_counts.add("facet_intervals", fi.intervalFacets);
rb.rsp.add("facet_counts", facet_counts);
@@ -637,6 +702,8 @@ public class FacetComponent extends Sear
= new SimpleOrderedMap<>();
public SimpleOrderedMap<SimpleOrderedMap<Object>> rangeFacets
= new SimpleOrderedMap<>();
+ public SimpleOrderedMap<SimpleOrderedMap<Integer>> intervalFacets
+ = new SimpleOrderedMap<>();
void parse(SolrParams params, ResponseBuilder rb) {
queryFacets = new LinkedHashMap<>();
Modified: lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/request/SimpleFacets.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/request/SimpleFacets.java?rev=1612958&r1=1612957&r2=1612958&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/request/SimpleFacets.java (original)
+++ lucene/dev/branches/branch_4x/solr/core/src/java/org/apache/solr/request/SimpleFacets.java Wed Jul 23 22:02:16 2014
@@ -72,6 +72,7 @@ import org.apache.solr.common.util.Named
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.common.util.StrUtils;
import org.apache.solr.handler.component.ResponseBuilder;
+import org.apache.solr.request.IntervalFacets.FacetInterval;
import org.apache.solr.schema.BoolField;
import org.apache.solr.schema.DateField;
import org.apache.solr.schema.FieldType;
@@ -245,6 +246,7 @@ public class SimpleFacets {
* @see #getFacetFieldCounts
* @see #getFacetDateCounts
* @see #getFacetRangeCounts
+ * @see #getFacetIntervalCounts
* @see FacetParams#FACET
* @return a NamedList of Facet Count info or null
*/
@@ -260,6 +262,7 @@ public class SimpleFacets {
facetResponse.add("facet_fields", getFacetFieldCounts());
facetResponse.add("facet_dates", getFacetDateCounts());
facetResponse.add("facet_ranges", getFacetRangeCounts());
+ facetResponse.add("facet_intervals", getFacetIntervalCounts());
} catch (IOException e) {
throw new SolrException(ErrorCode.SERVER_ERROR, e);
@@ -1557,6 +1560,41 @@ public class SimpleFacets {
return dmp.parseMath(gap);
}
}
-
+
+ /**
+ * Returns a <code>NamedList</code> with each entry having the "key" of the interval as name and the count of docs
+ * in that interval as value. All intervals added in the request are included in the returned
+ * <code>NamedList</code> (included those with 0 count), and it's required that the order of the intervals
+ * is deterministic and equals in all shards of a distributed request, otherwise the collation of results
+ * will fail.
+ *
+ */
+ public NamedList<Object> getFacetIntervalCounts() throws IOException, SyntaxError {
+ NamedList<Object> res = new SimpleOrderedMap<Object>();
+ String[] fields = params.getParams(FacetParams.FACET_INTERVAL);
+ if (fields == null || fields.length == 0) return res;
+
+ for (String field : fields) {
+ parseParams(FacetParams.FACET_INTERVAL, field);
+ String[] intervalStrs = required.getFieldParams(field, FacetParams.FACET_INTERVAL_SET);
+ SchemaField schemaField = searcher.getCore().getLatestSchema().getField(field);
+ if (!schemaField.hasDocValues()) {
+ throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Interval Faceting only on fields with doc values");
+ }
+ if (params.getBool(GroupParams.GROUP_FACET, false)) {
+ throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Interval Faceting can't be used with " + GroupParams.GROUP_FACET);
+ }
+
+ SimpleOrderedMap<Integer> fieldResults = new SimpleOrderedMap<Integer>();
+ res.add(field, fieldResults);
+ IntervalFacets intervalFacets = new IntervalFacets(schemaField, searcher, docs, intervalStrs);
+ for (FacetInterval interval : intervalFacets) {
+ fieldResults.add(interval.getKey(), interval.getCount());
+ }
+ }
+
+ return res;
+ }
+
}
Modified: lucene/dev/branches/branch_4x/solr/core/src/test-files/solr/collection1/conf/schema-docValuesFaceting.xml
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/core/src/test-files/solr/collection1/conf/schema-docValuesFaceting.xml?rev=1612958&r1=1612957&r2=1612958&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/solr/core/src/test-files/solr/collection1/conf/schema-docValuesFaceting.xml (original)
+++ lucene/dev/branches/branch_4x/solr/core/src/test-files/solr/collection1/conf/schema-docValuesFaceting.xml Wed Jul 23 22:02:16 2014
@@ -20,6 +20,9 @@
<types>
<fieldType name="int" class="solr.TrieIntField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="float" class="solr.TrieFloatField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+ <fieldType name="long" class="solr.TrieLongField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+ <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+ <fieldType name="date" class="solr.TrieDateField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
<fieldtype name="string" class="solr.StrField" sortMissingLast="true"/>
</types>
@@ -35,7 +38,17 @@
<dynamicField name="*_ss" type="string" indexed="true" stored="false" docValues="false" multiValued="true"/>
<dynamicField name="*_ss_dv" type="string" indexed="false" stored="false" docValues="true" multiValued="true"/>
<dynamicField name="*_f" type="float" indexed="true" stored="false" docValues="false"/>
- <dynamicField name="*_f_dv" type="float" indexed="false" stored="false" docValues="true"/>
+ <dynamicField name="*_f_dv" type="float" indexed="true" stored="false" docValues="true"/>
+ <dynamicField name="*_fs_dv" type="float" indexed="true" stored="false" docValues="true" multiValued="true"/>
+ <dynamicField name="*_l" type="long" indexed="true" stored="false" docValues="false"/>
+ <dynamicField name="*_l_dv" type="long" indexed="true" stored="false" docValues="true"/>
+ <dynamicField name="*_ls_dv" type="long" indexed="true" stored="false" docValues="true" multiValued="true"/>
+ <dynamicField name="*_d" type="double" indexed="true" stored="false" docValues="false"/>
+ <dynamicField name="*_d_dv" type="double" indexed="true" stored="false" docValues="true"/>
+ <dynamicField name="*_ds_dv" type="double" indexed="true" stored="false" docValues="true" multiValued="true"/>
+ <dynamicField name="*_dt" type="date" indexed="true" stored="false" docValues="false"/>
+ <dynamicField name="*_dt_dv" type="date" indexed="true" stored="false" docValues="true"/>
+ <dynamicField name="*_dts_dv" type="date" indexed="true" stored="false" docValues="true" multiValued="true"/>
</fields>
<defaultSearchField>id</defaultSearchField>
Copied: lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/DistributedIntervalFacetingTest.java (from r1612889, lucene/dev/trunk/solr/core/src/test/org/apache/solr/DistributedIntervalFacetingTest.java)
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/DistributedIntervalFacetingTest.java?p2=lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/DistributedIntervalFacetingTest.java&p1=lucene/dev/trunk/solr/core/src/test/org/apache/solr/DistributedIntervalFacetingTest.java&r1=1612889&r2=1612958&rev=1612958&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/DistributedIntervalFacetingTest.java (original)
+++ lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/DistributedIntervalFacetingTest.java Wed Jul 23 22:02:16 2014
@@ -25,7 +25,7 @@ import org.junit.BeforeClass;
* limitations under the License.
*/
@Slow
-@LuceneTestCase.SuppressCodecs({"Lucene40", "Lucene41", "Lucene42", "Lucene43"})
+@LuceneTestCase.SuppressCodecs({"Lucene3x", "Lucene40", "Lucene41", "Lucene42", "Lucene43"})
public class DistributedIntervalFacetingTest extends
BaseDistributedSearchTestCase {
Modified: lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/TestGroupingSearch.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/TestGroupingSearch.java?rev=1612958&r1=1612957&r2=1612958&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/TestGroupingSearch.java (original)
+++ lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/TestGroupingSearch.java Wed Jul 23 22:02:16 2014
@@ -318,7 +318,7 @@ public class TestGroupingSearch extends
assertJQ(
req,
"/grouped=={'value1_s1':{'matches':5,'groups':[{'groupValue':'1','doclist':{'numFound':3,'start':0,'docs':[{'id':'1'}]}}]}}",
- "/facet_counts=={'facet_queries':{},'facet_fields':{'value3_s1':['a',3,'b',2]},'facet_dates':{},'facet_ranges':{}}"
+ "/facet_counts=={'facet_queries':{},'facet_fields':{'value3_s1':['a',3,'b',2]},'facet_dates':{},'facet_ranges':{},'facet_intervals':{}}"
);
// Facet counts based on groups
@@ -327,7 +327,7 @@ public class TestGroupingSearch extends
assertJQ(
req,
"/grouped=={'value1_s1':{'matches':5,'groups':[{'groupValue':'1','doclist':{'numFound':3,'start':0,'docs':[{'id':'1'}]}}]}}",
- "/facet_counts=={'facet_queries':{},'facet_fields':{'value3_s1':['a',1,'b',1]},'facet_dates':{},'facet_ranges':{}}"
+ "/facet_counts=={'facet_queries':{},'facet_fields':{'value3_s1':['a',1,'b',1]},'facet_dates':{},'facet_ranges':{},'facet_intervals':{}}"
);
// Facet counts based on groups and with group.func. This should trigger FunctionAllGroupHeadsCollector
@@ -336,7 +336,7 @@ public class TestGroupingSearch extends
assertJQ(
req,
"/grouped=={'strdist(1,value1_s1,edit)':{'matches':5,'groups':[{'groupValue':1.0,'doclist':{'numFound':3,'start':0,'docs':[{'id':'1'}]}}]}}",
- "/facet_counts=={'facet_queries':{},'facet_fields':{'value3_s1':['a',1,'b',1]},'facet_dates':{},'facet_ranges':{}}"
+ "/facet_counts=={'facet_queries':{},'facet_fields':{'value3_s1':['a',1,'b',1]},'facet_dates':{},'facet_ranges':{},'facet_intervals':{}}"
);
// Facet counts based on groups without sort on an int field.
@@ -345,7 +345,7 @@ public class TestGroupingSearch extends
assertJQ(
req,
"/grouped=={'value4_i':{'matches':5,'groups':[{'groupValue':1,'doclist':{'numFound':3,'start':0,'docs':[{'id':'1'}]}}]}}",
- "/facet_counts=={'facet_queries':{},'facet_fields':{'value3_s1':['a',1,'b',1]},'facet_dates':{},'facet_ranges':{}}"
+ "/facet_counts=={'facet_queries':{},'facet_fields':{'value3_s1':['a',1,'b',1]},'facet_dates':{},'facet_ranges':{},'facet_intervals':{}}"
);
// Multi select facets AND group.truncate=true
@@ -354,7 +354,7 @@ public class TestGroupingSearch extends
assertJQ(
req,
"/grouped=={'value4_i':{'matches':2,'groups':[{'groupValue':2,'doclist':{'numFound':2,'start':0,'docs':[{'id':'3'}]}}]}}",
- "/facet_counts=={'facet_queries':{},'facet_fields':{'value3_s1':['a',1,'b',1]},'facet_dates':{},'facet_ranges':{}}"
+ "/facet_counts=={'facet_queries':{},'facet_fields':{'value3_s1':['a',1,'b',1]},'facet_dates':{},'facet_ranges':{},'facet_intervals':{}}"
);
// Multi select facets AND group.truncate=false
@@ -363,7 +363,7 @@ public class TestGroupingSearch extends
assertJQ(
req,
"/grouped=={'value4_i':{'matches':2,'groups':[{'groupValue':2,'doclist':{'numFound':2,'start':0,'docs':[{'id':'3'}]}}]}}",
- "/facet_counts=={'facet_queries':{},'facet_fields':{'value3_s1':['a',3,'b',2]},'facet_dates':{},'facet_ranges':{}}"
+ "/facet_counts=={'facet_queries':{},'facet_fields':{'value3_s1':['a',3,'b',2]},'facet_dates':{},'facet_ranges':{},'facet_intervals':{}}"
);
// Multi select facets AND group.truncate=true
@@ -372,7 +372,7 @@ public class TestGroupingSearch extends
assertJQ(
req,
"/grouped=={'sub(value4_i,1)':{'matches':2,'groups':[{'groupValue':1.0,'doclist':{'numFound':2,'start':0,'docs':[{'id':'3'}]}}]}}",
- "/facet_counts=={'facet_queries':{},'facet_fields':{'value3_s1':['a',1,'b',1]},'facet_dates':{},'facet_ranges':{}}"
+ "/facet_counts=={'facet_queries':{},'facet_fields':{'value3_s1':['a',1,'b',1]},'facet_dates':{},'facet_ranges':{},'facet_intervals':{}}"
);
}
@@ -395,7 +395,7 @@ public class TestGroupingSearch extends
assertJQ(
req,
"/grouped=={'cat_sI':{'matches':2,'groups':[{'groupValue':'a','doclist':{'numFound':1,'start':0,'docs':[{'id':'5'}]}}]}}",
- "/facet_counts=={'facet_queries':{'LW1':2,'LM1':2,'LM3':2},'facet_fields':{},'facet_dates':{},'facet_ranges':{}}"
+ "/facet_counts=={'facet_queries':{'LW1':2,'LM1':2,'LM3':2},'facet_fields':{},'facet_dates':{},'facet_ranges':{},'facet_intervals':{}}"
);
}
Copied: lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/request/TestIntervalFaceting.java (from r1612889, lucene/dev/trunk/solr/core/src/test/org/apache/solr/request/TestIntervalFaceting.java)
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/request/TestIntervalFaceting.java?p2=lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/request/TestIntervalFaceting.java&p1=lucene/dev/trunk/solr/core/src/test/org/apache/solr/request/TestIntervalFaceting.java&r1=1612889&r2=1612958&rev=1612958&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/request/TestIntervalFaceting.java (original)
+++ lucene/dev/branches/branch_4x/solr/core/src/test/org/apache/solr/request/TestIntervalFaceting.java Wed Jul 23 22:02:16 2014
@@ -36,7 +36,7 @@ import org.apache.solr.util.RefCounted;
import org.junit.BeforeClass;
import org.junit.Test;
-@LuceneTestCase.SuppressCodecs({"Lucene40", "Lucene41", "Lucene42", "Lucene43"})
+@LuceneTestCase.SuppressCodecs({"Lucene3x", "Lucene40", "Lucene41", "Lucene42", "Lucene43"})
public class TestIntervalFaceting extends SolrTestCaseJ4 {
@BeforeClass
Modified: lucene/dev/branches/branch_4x/solr/solrj/src/java/org/apache/solr/common/params/FacetParams.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/solrj/src/java/org/apache/solr/common/params/FacetParams.java?rev=1612958&r1=1612957&r2=1612958&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/solr/solrj/src/java/org/apache/solr/common/params/FacetParams.java (original)
+++ lucene/dev/branches/branch_4x/solr/solrj/src/java/org/apache/solr/common/params/FacetParams.java Wed Jul 23 22:02:16 2014
@@ -254,6 +254,15 @@ public interface FacetParams {
*/
public static final String FACET_RANGE_INCLUDE = FACET_RANGE + ".include";
+ /**
+ * Any field whose values the user wants to enumerate as explicit intervals of terms.
+ */
+ public static final String FACET_INTERVAL = FACET + ".interval";
+
+ /**
+ * Set of terms for a single interval to facet on.
+ */
+ public static final String FACET_INTERVAL_SET = FACET_INTERVAL + ".set";
/**
* An enumeration of the legal values for {@link #FACET_RANGE_OTHER} and {@link #FACET_DATE_OTHER} ...
Modified: lucene/dev/branches/branch_4x/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java?rev=1612958&r1=1612957&r2=1612958&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java (original)
+++ lucene/dev/branches/branch_4x/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java Wed Jul 23 22:02:16 2014
@@ -839,6 +839,28 @@ public abstract class SolrTestCaseJ4 ext
unIgnoreException(".");
}
}
+ /**
+ * Makes sure a query throws a SolrException with the listed response code and expected message
+ * @param failMessage The assert message to show when the query doesn't throw the expected exception
+ * @param exceptionMessage A substring of the message expected in the exception
+ * @param req Solr request
+ * @param code expected error code for the query
+ */
+ public static void assertQEx(String failMessage, String exceptionMessage, SolrQueryRequest req, SolrException.ErrorCode code ) {
+ try {
+ ignoreException(".");
+ h.query(req);
+ fail( failMessage );
+ } catch (SolrException e) {
+ assertEquals( code.code, e.code() );
+ assertTrue("Unexpected error message. Expecting \"" + exceptionMessage +
+ "\" but got \"" + e.getMessage() + "\"", e.getMessage()!= null && e.getMessage().contains(exceptionMessage));
+ } catch (Exception e2) {
+ throw new RuntimeException("Exception during query", e2);
+ } finally {
+ unIgnoreException(".");
+ }
+ }
/**