diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 89a9ee82d80..ab676072507 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -108,6 +108,9 @@ New Features * SOLR-7005: Spatial 2D heatmap faceting on RPT fields via new facet.heatmap with PNG and 2D int array formats. (David Smiley) +* SOLR-7019: Support changing field key when using interval faceting. + (Tomás Fernández Löbbe) + Bug Fixes ---------------------- diff --git a/solr/core/src/java/org/apache/solr/request/SimpleFacets.java b/solr/core/src/java/org/apache/solr/request/SimpleFacets.java index 6a63578ae53..d3f287ac14b 100644 --- a/solr/core/src/java/org/apache/solr/request/SimpleFacets.java +++ b/solr/core/src/java/org/apache/solr/request/SimpleFacets.java @@ -1500,8 +1500,8 @@ public class SimpleFacets { 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); + String[] intervalStrs = required.getFieldParams(facetValue, FacetParams.FACET_INTERVAL_SET); + SchemaField schemaField = searcher.getCore().getLatestSchema().getField(facetValue); if (!schemaField.hasDocValues()) { throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Interval Faceting only on fields with doc values"); } @@ -1510,7 +1510,7 @@ public class SimpleFacets { } SimpleOrderedMap fieldResults = new SimpleOrderedMap(); - res.add(field, fieldResults); + res.add(key, fieldResults); IntervalFacets intervalFacets = new IntervalFacets(schemaField, searcher, docs, intervalStrs, params); for (FacetInterval interval : intervalFacets) { fieldResults.add(interval.getKey(), interval.getCount()); diff --git a/solr/core/src/test/org/apache/solr/DistributedIntervalFacetingTest.java b/solr/core/src/test/org/apache/solr/DistributedIntervalFacetingTest.java index b6d0bfaf3e7..e5efa6fae28 100644 --- a/solr/core/src/test/org/apache/solr/DistributedIntervalFacetingTest.java +++ b/solr/core/src/test/org/apache/solr/DistributedIntervalFacetingTest.java @@ -175,7 +175,11 @@ public class DistributedIntervalFacetingTest extends params.set("facet", "true"); params.set("rows", "0"); String field = fields[random().nextInt(fields.length)]; //choose from any of the fields - params.set("facet.interval", field); + if (random().nextBoolean()) { + params.set("facet.interval", field); + } else { + params.set("facet.interval", getFieldWithKey(field)); + } // number of intervals for (int i = 0; i < 1 + random().nextInt(20); i++) { Integer[] interval = getRandomRange(cardinality, field); @@ -187,6 +191,10 @@ public class DistributedIntervalFacetingTest extends } + private String getFieldWithKey(String field) { + return "{!key='_some_key_for_" + field + "_" + System.currentTimeMillis() + "'}" + field; + } + /** * Returns a random range. It's guaranteed that the first * number will be lower than the second, and both of them diff --git a/solr/core/src/test/org/apache/solr/request/TestIntervalFaceting.java b/solr/core/src/test/org/apache/solr/request/TestIntervalFaceting.java index 508c0ceabf6..ffb094ee0a6 100644 --- a/solr/core/src/test/org/apache/solr/request/TestIntervalFaceting.java +++ b/solr/core/src/test/org/apache/solr/request/TestIntervalFaceting.java @@ -22,6 +22,10 @@ import java.util.Comparator; import org.apache.lucene.util.BytesRef; import org.apache.solr.SolrTestCaseJ4; +import org.apache.solr.client.solrj.SolrClient; +import org.apache.solr.client.solrj.SolrQuery; +import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer; +import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrException; import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.util.NamedList; @@ -840,6 +844,95 @@ public class TestIntervalFaceting extends SolrTestCaseJ4 { assertIntervalQueriesString("test_s_dv"); } + + @Test + public void testChangeFieldKey() { + assertU(adoc("id", "1", "test_s_dv", "dog", "test_l_dv", "1")); + assertU(adoc("id", "2", "test_s_dv", "cat", "test_l_dv", "2")); + assertU(commit()); + + assertQ(req("q", "*:*", "facet", "true", "facet.interval", "{!key=foo}test_s_dv", + "facet.interval", "{!key=bar}test_l_dv", "f.test_s_dv.facet.interval.set", "[cat,dog]", + "f.test_l_dv.facet.interval.set", "[0,1]", + "f.test_l_dv.facet.interval.set", "[2,*]"), + "//lst[@name='facet_intervals']/lst[@name='foo']/int[@name='[cat,dog]'][.=2]", + "//lst[@name='facet_intervals']/lst[@name='bar']/int[@name='[0,1]'][.=1]", + "//lst[@name='facet_intervals']/lst[@name='bar']/int[@name='[2,*]'][.=1]"); + } + + + @Test + public void testFilterExclusion() { + 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", "rows", "0", + "f.test_s_dv.facet.interval.set", "[a,d]", + "f.test_s_dv.facet.interval.set", "[d,z]"), + "//lst[@name='facet_intervals']/lst[@name='test_s_dv']/int[@name='[a,d]'][.=4]", + "//lst[@name='facet_intervals']/lst[@name='test_s_dv']/int[@name='[d,z]'][.=5]"); + + assertQ(req("q", "*:*", "facet", "true", "facet.interval", "test_s_dv", "rows", "0", + "f.test_s_dv.facet.interval.set", "[a,d]", + "f.test_s_dv.facet.interval.set", "[d,z]", + "fq", "test_s_dv:dog"), + "//lst[@name='facet_intervals']/lst[@name='test_s_dv']/int[@name='[a,d]'][.=0]", + "//lst[@name='facet_intervals']/lst[@name='test_s_dv']/int[@name='[d,z]'][.=4]"); + + assertQ(req("q", "*:*", "facet", "true", "facet.interval", "{!ex=dogs}test_s_dv", "rows", "0", + "f.test_s_dv.facet.interval.set", "[a,d]", + "f.test_s_dv.facet.interval.set", "[d,z]", + "fq", "{!tag='dogs'}test_s_dv:dog"), + "//lst[@name='facet_intervals']/lst[@name='test_s_dv']/int[@name='[a,d]'][.=4]", + "//lst[@name='facet_intervals']/lst[@name='test_s_dv']/int[@name='[d,z]'][.=5]"); + } + + @Test + public void testSolrJ() throws Exception { + assertU(adoc("id", "1", "test_i_dv", "0")); + assertU(adoc("id", "2", "test_i_dv", "1")); + assertU(adoc("id", "3", "test_i_dv", "2")); + assertU(commit()); + + // Don't close this client, it would shutdown the CoreContainer + @SuppressWarnings("resource") + SolrClient client = new EmbeddedSolrServer(h.getCore()); + + SolrQuery q = new SolrQuery(); + q.setQuery("*:*"); + q.addIntervalFacets("test_i_dv", new String[]{"[0,1]","[2,*]"}); + QueryResponse response = client.query(q); + assertEquals(1, response.getIntervalFacets().size()); + assertEquals("test_i_dv", response.getIntervalFacets().get(0).getField()); + assertEquals(2, response.getIntervalFacets().get(0).getIntervals().size()); + assertEquals("[0,1]", response.getIntervalFacets().get(0).getIntervals().get(0).getKey()); + assertEquals("[2,*]", response.getIntervalFacets().get(0).getIntervals().get(1).getKey()); + + q = new SolrQuery(); + q.setQuery("*:*"); + q.setFacet(true); + q.add("facet.interval", "{!key=foo}test_i_dv"); + q.add("f.test_i_dv.facet.interval.set", "{!key=first}[0,1]"); + q.add("f.test_i_dv.facet.interval.set", "{!key=second}[2,*]"); + response = client.query(q); + assertEquals(1, response.getIntervalFacets().size()); + assertEquals("foo", response.getIntervalFacets().get(0).getField()); + assertEquals(2, response.getIntervalFacets().get(0).getIntervals().size()); + assertEquals("first", response.getIntervalFacets().get(0).getIntervals().get(0).getKey()); + assertEquals("second", response.getIntervalFacets().get(0).getIntervals().get(1).getKey()); + + } + + private void assertIntervalQueriesNumeric(String field) { assertIntervalQuery(field, "[0,1]", "2"); diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/SolrQuery.java b/solr/solrj/src/java/org/apache/solr/client/solrj/SolrQuery.java index 221c338a12d..bda6f343f82 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/SolrQuery.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/SolrQuery.java @@ -277,9 +277,14 @@ public class SolrQuery extends ModifiableSolrParams /** * Add Interval Faceting on a field. All intervals for the same field should be included * in the same call to this method. - * For syntax documentation see Solr wiki + * For syntax documentation see Solr wiki. + *
+ * Key substitution, filter exclusions or other local params on the field are not supported when using this method, + * if this is needed, use the lower level {@link #add} method.
+ * Key substitution IS supported on intervals when using this method. * - * @param field the field to add facet intervals + * + * @param field the field to add facet intervals. Must be an existing field and can't be null * @param intervals Intervals to be used for faceting. It can be an empty array, but it can't * be null * @return this @@ -288,6 +293,9 @@ public class SolrQuery extends ModifiableSolrParams if (intervals == null) { throw new IllegalArgumentException("Can't add null intervals"); } + if (field == null) { + throw new IllegalArgumentException("Field can't be null"); + } set(FacetParams.FACET, true); add(FacetParams.FACET_INTERVAL, field); for (String interval:intervals) {