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 23:43:19 UTC
svn commit: r1613308 - in /lucene/dev/trunk/solr: CHANGES.txt
core/src/java/org/apache/solr/request/IntervalFacets.java
core/src/java/org/apache/solr/request/SimpleFacets.java
core/src/test/org/apache/solr/request/TestIntervalFaceting.java
Author: erick
Date: Thu Jul 24 21:43:18 2014
New Revision: 1613308
URL: http://svn.apache.org/r1613308
Log:
SOLR-6267: Let user override Interval Faceting key with LocalParams. Thanks Tomas
Modified:
lucene/dev/trunk/solr/CHANGES.txt
lucene/dev/trunk/solr/core/src/java/org/apache/solr/request/IntervalFacets.java
lucene/dev/trunk/solr/core/src/java/org/apache/solr/request/SimpleFacets.java
lucene/dev/trunk/solr/core/src/test/org/apache/solr/request/TestIntervalFaceting.java
Modified: lucene/dev/trunk/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/CHANGES.txt?rev=1613308&r1=1613307&r2=1613308&view=diff
==============================================================================
--- lucene/dev/trunk/solr/CHANGES.txt (original)
+++ lucene/dev/trunk/solr/CHANGES.txt Thu Jul 24 21:43:18 2014
@@ -158,6 +158,9 @@ New Features
* SOLR-6216: Better faceting for multiple intervals on DV fields (Tomas Fernandez-Lobbe
via Erick Erickson)
+* SOLR-6267: Let user override Interval Faceting key with LocalParams (Tomas Fernandez_Lobbe
+ via Erick Erickson)
+
Bug Fixes
----------------------
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/request/IntervalFacets.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/request/IntervalFacets.java?rev=1613308&r1=1613307&r2=1613308&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/request/IntervalFacets.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/request/IntervalFacets.java Thu Jul 24 21:43:18 2014
@@ -22,12 +22,15 @@ import org.apache.lucene.util.Bits;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.NumericUtils;
import org.apache.solr.common.SolrException;
+import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.params.SolrParams;
import org.apache.solr.request.IntervalFacets.FacetInterval;
import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.schema.TrieDateField;
import org.apache.solr.search.DocIterator;
import org.apache.solr.search.DocSet;
+import org.apache.solr.search.QueryParsing;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.search.SyntaxError;
@@ -60,7 +63,7 @@ import org.apache.solr.search.SyntaxErro
* be faster in cases where there are a larger number of intervals per field.
* <p/>
* To use this class, create an instance using
- * {@link #IntervalFacets(SchemaField, SolrIndexSearcher, DocSet, String[])}
+ * {@link #IntervalFacets(SchemaField, SolrIndexSearcher, DocSet, String[], SolrParams)}
* and then iterate the {@link FacetInterval} using {@link #iterator()}
* <p/>
* Intervals Format</br>
@@ -82,11 +85,14 @@ import org.apache.solr.search.SyntaxErro
* comparator can't be changed.
* Commas, brackets and square brackets can be escaped by using '\' in front of them.
* Whitespaces before and after the values will be omitted. Start limit can't be grater
- * than the end limit. Equal limits are allowed.
+ * than the end limit. Equal limits are allowed.<p>
+ * As with facet.query, the key used to display the result can be set by using local params
+ * syntax, for example:<p>
+ * <code>{!key='First Half'}[0,5) </code>
* <p/>
* To use this class:
* <pre>
- * IntervalFacets intervalFacets = new IntervalFacets(schemaField, searcher, docs, intervalStrs);
+ * IntervalFacets intervalFacets = new IntervalFacets(schemaField, searcher, docs, intervalStrs, params);
* for (FacetInterval interval : intervalFacets) {
* results.add(interval.getKey(), interval.getCount());
* }
@@ -98,19 +104,19 @@ public class IntervalFacets implements I
private final DocSet docs;
private final FacetInterval[] intervals;
- public IntervalFacets(SchemaField schemaField, SolrIndexSearcher searcher, DocSet docs, String[] intervals) throws SyntaxError, IOException {
+ public IntervalFacets(SchemaField schemaField, SolrIndexSearcher searcher, DocSet docs, String[] intervals, SolrParams params) throws SyntaxError, IOException {
this.schemaField = schemaField;
this.searcher = searcher;
this.docs = docs;
- this.intervals = getSortedIntervals(intervals);
+ this.intervals = getSortedIntervals(intervals, params);
doCount();
}
- private FacetInterval[] getSortedIntervals(String[] intervals) throws SyntaxError {
+ private FacetInterval[] getSortedIntervals(String[] intervals, SolrParams params) throws SyntaxError {
FacetInterval[] sortedIntervals = new FacetInterval[intervals.length];
int idx = 0;
for (String intervalStr : intervals) {
- sortedIntervals[idx++] = new FacetInterval(schemaField, intervalStr);
+ sortedIntervals[idx++] = new FacetInterval(schemaField, intervalStr, params);
}
/*
@@ -400,11 +406,31 @@ public class IntervalFacets implements I
*/
private int count;
- FacetInterval(SchemaField schemaField, String intervalStr) throws SyntaxError {
+ FacetInterval(SchemaField schemaField, String intervalStr, SolrParams params) throws SyntaxError {
if (intervalStr == null) throw new SyntaxError("empty facet interval");
intervalStr = intervalStr.trim();
if (intervalStr.length() == 0) throw new SyntaxError("empty facet interval");
- key = intervalStr;
+
+ try {
+ SolrParams localParams = QueryParsing.getLocalParams(intervalStr, params);
+ if (localParams != null ) {
+ int localParamEndIdx = 2; // omit index of {!
+ while (true) {
+ localParamEndIdx = intervalStr.indexOf(QueryParsing.LOCALPARAM_END, localParamEndIdx);
+ // Local param could be escaping '}'
+ if (intervalStr.charAt(localParamEndIdx - 1) != '\\') {
+ break;
+ }
+ localParamEndIdx++;
+ }
+ intervalStr = intervalStr.substring(localParamEndIdx + 1);
+ key = localParams.get(CommonParams.OUTPUT_KEY, intervalStr);
+ } else {
+ key = intervalStr;
+ }
+ } catch (SyntaxError e) {
+ throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, e);
+ }
if (intervalStr.charAt(0) == '(') {
startOpen = true;
} else if (intervalStr.charAt(0) == '[') {
Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/request/SimpleFacets.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/request/SimpleFacets.java?rev=1613308&r1=1613307&r2=1613308&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/request/SimpleFacets.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/request/SimpleFacets.java Thu Jul 24 21:43:18 2014
@@ -17,6 +17,26 @@
package org.apache.solr.request;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.EnumSet;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.RunnableFuture;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
import org.apache.lucene.index.AtomicReader;
import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.index.DocsEnum;
@@ -74,26 +94,6 @@ import org.apache.solr.util.BoundedTreeS
import org.apache.solr.util.DateMathParser;
import org.apache.solr.util.DefaultSolrThreadFactory;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.EnumSet;
-import java.util.IdentityHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Future;
-import java.util.concurrent.FutureTask;
-import java.util.concurrent.RunnableFuture;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.SynchronousQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
/**
* A class that generates simple Facet information for a request.
*
@@ -1433,7 +1433,7 @@ public class SimpleFacets {
SimpleOrderedMap<Integer> fieldResults = new SimpleOrderedMap<Integer>();
res.add(field, fieldResults);
- IntervalFacets intervalFacets = new IntervalFacets(schemaField, searcher, docs, intervalStrs);
+ IntervalFacets intervalFacets = new IntervalFacets(schemaField, searcher, docs, intervalStrs, params);
for (FacetInterval interval : intervalFacets) {
fieldResults.add(interval.getKey(), interval.getCount());
}
Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/request/TestIntervalFaceting.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/request/TestIntervalFaceting.java?rev=1613308&r1=1613307&r2=1613308&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/request/TestIntervalFaceting.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/request/TestIntervalFaceting.java Thu Jul 24 21:43:18 2014
@@ -389,6 +389,24 @@ public class TestIntervalFaceting extend
assertBadInterval("test_s_dv", "(B,A)", "Start is higher than end in interval for key");
assertBadInterval("test_s_dv", "(a,B)", "Start is higher than end in interval for key");
+ assertIntervalKey("test_s_dv", "[A,B]", "[A,B]");
+ assertIntervalKey("test_s_dv", "(A,*]", "(A,*]");
+ assertIntervalKey("test_s_dv", "{!}(A,*]", "(A,*]");
+ assertIntervalKey("test_s_dv", "{!key=foo}(A,*]", "foo");
+ assertIntervalKey("test_s_dv", "{!key='foo'}(A,*]", "foo");
+ assertIntervalKey("test_s_dv", "{!key='foo bar'}(A,*]", "foo bar");
+ assertIntervalKey("test_s_dv", "{!key='foo' bar}(A,*]", "foo");
+ assertIntervalKey("test_s_dv", "{!key=$i}(A,*]", "foo", "i", "foo");
+ assertIntervalKey("test_s_dv", "{!key=$i}(A,*]", "foo bar", "i", "foo bar");
+ assertIntervalKey("test_s_dv", "{!key=$i}(A,*]", "'foo'", "i", "'foo'");
+ assertIntervalKey("test_s_dv", "{!key=$i}(A,*]", "\"foo\"", "i", "\"foo\"");
+ assertIntervalKey("test_s_dv", "{!key='[A,B]'}(A,B)", "[A,B]");
+ assertIntervalKey("test_s_dv", "{!key='\\{\\{\\{'}(A,B)", "{{{");
+ assertIntervalKey("test_s_dv", "{!key='\\{A,B\\}'}(A,B)", "{A,B}");
+ assertIntervalKey("test_s_dv", "{!key='\"A,B\"'}(A,B)", "\"A,B\"");
+ assertIntervalKey("test_s_dv", "{!key='A..B'}(A,B)", "A..B");
+ assertIntervalKey("test_s_dv", "{!key='A TO B'}(A,B)", "A TO B");
+
assertU(adoc("id", "1", "test_s_dv", "dog", "test_l_dv", "1"));
assertU(adoc("id", "2", "test_s_dv", "cat", "test_l_dv", "2"));
@@ -496,7 +514,7 @@ public class TestIntervalFaceting extend
private void assertStringInterval(String fieldName, String intervalStr,
String expectedStart, String expectedEnd) throws SyntaxError {
SchemaField f = h.getCore().getLatestSchema().getField(fieldName);
- FacetInterval interval = new FacetInterval(f, intervalStr);
+ FacetInterval interval = new FacetInterval(f, intervalStr, new ModifiableSolrParams());
assertEquals("Expected start " + expectedStart + " but found " + f.getType().toObject(f, interval.start),
interval.start, new BytesRef(f.getType().toInternal(expectedStart)));
@@ -508,7 +526,7 @@ public class TestIntervalFaceting extend
private void assertBadInterval(String fieldName, String intervalStr, String errorMsg) {
SchemaField f = h.getCore().getLatestSchema().getField(fieldName);
try {
- new FacetInterval(f, intervalStr);
+ new FacetInterval(f, intervalStr, new ModifiableSolrParams());
fail("Expecting SyntaxError for interval String: " + intervalStr);
} catch (SyntaxError e) {
assertTrue("Unexpected error message for interval String: " + intervalStr + ": " +
@@ -518,7 +536,7 @@ public class TestIntervalFaceting extend
private void assertInterval(String fieldName, String intervalStr, long[] included, long[] lowerThanStart, long[] graterThanEnd) throws SyntaxError {
SchemaField f = h.getCore().getLatestSchema().getField(fieldName);
- FacetInterval interval = new FacetInterval(f, intervalStr);
+ FacetInterval interval = new FacetInterval(f, intervalStr, new ModifiableSolrParams());
for (long l : included) {
assertEquals("Value " + l + " should be INCLUDED for interval" + interval,
IntervalCompareResult.INCLUDED, interval.includes(l));
@@ -533,6 +551,61 @@ public class TestIntervalFaceting extend
}
}
+
+ private void assertIntervalKey(String fieldName, String intervalStr,
+ String expectedKey, String...params) throws SyntaxError {
+ assert (params.length&1)==0:"Params must have an even number of elements";
+ SchemaField f = h.getCore().getLatestSchema().getField(fieldName);
+ ModifiableSolrParams solrParams = new ModifiableSolrParams();
+ for (int i = 0; i < params.length - 1;) {
+ solrParams.set(params[i], params[i+1]);
+ i+=2;
+ }
+ FacetInterval interval = new FacetInterval(f, intervalStr, solrParams);
+
+ assertEquals("Expected key " + expectedKey + " but found " + interval.getKey(),
+ expectedKey, interval.getKey());
+ }
+
+ public void testChangeKey() {
+ assertU(adoc("id", "1", "test_s_dv", "dog"));
+ assertU(adoc("id", "2", "test_s_dv", "cat"));
+ assertU(adoc("id", "3", "test_s_dv", "bird"));
+ assertU(adoc("id", "4", "test_s_dv", "cat"));
+ assertU(adoc("id", "5", "test_s_dv", "turtle"));
+ assertU(adoc("id", "6", "test_s_dv", "dog"));
+ assertU(adoc("id", "7", "test_s_dv", "dog"));
+ assertU(adoc("id", "8", "test_s_dv", "dog"));
+ assertU(adoc("id", "9", "test_s_dv", "cat"));
+ assertU(adoc("id", "10"));
+ assertU(commit());
+
+ assertQ(req("q", "*:*", "facet", "true", "facet.interval", "test_s_dv",
+ "f.test_s_dv.facet.interval.set", "{!key=foo}[bird,bird]",
+ "f.test_s_dv.facet.interval.set", "{!key='bar'}(bird,dog)"),
+ "//lst[@name='facet_intervals']/lst[@name='test_s_dv']/int[@name='foo'][.=1]",
+ "//lst[@name='facet_intervals']/lst[@name='test_s_dv']/int[@name='bar'][.=3]");
+
+ assertQ(req("q", "*:*", "facet", "true", "facet.interval", "test_s_dv",
+ "f.test_s_dv.facet.interval.set", "{!key=Birds}[bird,bird]",
+ "f.test_s_dv.facet.interval.set", "{!key='foo bar'}(bird,dog)"),
+ "//lst[@name='facet_intervals']/lst[@name='test_s_dv']/int[@name='Birds'][.=1]",
+ "//lst[@name='facet_intervals']/lst[@name='test_s_dv']/int[@name='foo bar'][.=3]");
+
+ assertQ(req("q", "*:*", "facet", "true", "facet.interval", "test_s_dv",
+ "f.test_s_dv.facet.interval.set", "{!key=$p}[bird,bird]",
+ "p", "foo bar"),
+ "//lst[@name='facet_intervals']/lst[@name='test_s_dv']/int[@name='foo bar'][.=1]");
+
+ assertQ(req("q", "*:*", "facet", "true", "facet.interval", "test_s_dv",
+ "f.test_s_dv.facet.interval.set", "{!key='[bird,\\}'}[bird,*]",
+ "f.test_s_dv.facet.interval.set", "{!key='\\{bird,dog\\}'}(bird,dog)",
+ "f.test_s_dv.facet.interval.set", "{!key='foo'}(bird,dog})"),
+ "//lst[@name='facet_intervals']/lst[@name='test_s_dv']/int[@name='[bird,}'][.=9]",
+ "//lst[@name='facet_intervals']/lst[@name='test_s_dv']/int[@name='{bird,dog}'][.=3]",
+ "//lst[@name='facet_intervals']/lst[@name='test_s_dv']/int[@name='foo'][.=7]");
+
+ }
@Test
public void testLongFields() {
@@ -755,7 +828,7 @@ public class TestIntervalFaceting extend
assertIntervalQuery(field, "[0,2)", "2");
assertIntervalQuery(field, "(0,2]", "2");
assertIntervalQuery(field, "[*,5]", "6");
- assertIntervalQuery(field, "[*,3)", "3", "[2,5)", "3", "[6,8)", "2", "[3,*]", "7", "[10,10]", "1");
+ assertIntervalQuery(field, "[*,3)", "3", "[2,5)", "3", "[6,8)", "2", "[3,*]", "7", "[10,10]", "1", "[10,10]", "1", "[10,10]", "1");
}