diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index bb36297d4ae..20140209097 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -294,6 +294,9 @@ Bug Fixes * SOLR-8804: Fix a race condition in the ClusterStatus API call whereby the call would fail when a concurrent delete collection api command was executed (Alexey Serba, Varun Thacker) +* SOLR-8835: JSON Facet API: fix faceting exception on multi-valued numeric fields that + have docValues. (yonik) + Optimizations ---------------------- * SOLR-7876: Speed up queries and operations that use many terms when timeAllowed has not been diff --git a/solr/core/src/java/org/apache/solr/search/facet/FacetField.java b/solr/core/src/java/org/apache/solr/search/facet/FacetField.java index a1f113196c3..ce7f9198f83 100644 --- a/solr/core/src/java/org/apache/solr/search/facet/FacetField.java +++ b/solr/core/src/java/org/apache/solr/search/facet/FacetField.java @@ -125,13 +125,8 @@ public class FacetField extends FacetRequest { org.apache.lucene.document.FieldType.LegacyNumericType ntype = ft.getNumericType(); - if (sf.hasDocValues() && ntype==null) { - // single and multi-valued string docValues - return new FacetFieldProcessorDV(fcontext, this, sf); - } - if (!multiToken) { - if (sf.getType().getNumericType() != null) { + if (ntype != null) { // single valued numeric (docvalues or fieldcache) return new FacetFieldProcessorNumeric(fcontext, this, sf); } else { @@ -140,8 +135,10 @@ public class FacetField extends FacetRequest { } } - // multivalued but field doesn't have docValues - if (method == FacetMethod.DV) { + // multi-valued after this point + + if (sf.hasDocValues() || method == FacetMethod.DV) { + // single and multi-valued string docValues return new FacetFieldProcessorDV(fcontext, this, sf); } diff --git a/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java b/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java index 83220edc468..8aaede16862 100644 --- a/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java +++ b/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java @@ -343,25 +343,27 @@ public class TestJsonFacets extends SolrTestCaseHS { doStatsTemplated(client, params(p, "rows","0", "noexist","noexist_s", "cat_s","cat_s", "where_s","where_s", "num_d","num_d", "num_i","num_i", "super_s","super_s", "val_b","val_b", "date","date_dt", "sparse_s","sparse_s" ,"multi_ss","multi_ss") ); // multi-valued strings, long/float substitute for int/double - doStatsTemplated(client, params(p, "facet","true", "rows","0", "noexist","noexist_ss", "cat_s","cat_ss", "where_s","where_ss", "num_d","num_f", "num_i","num_l", "super_s","super_ss", "val_b","val_b", "date","date_dt", "sparse_s","sparse_ss", "multi_ss","multi_ss") ); + doStatsTemplated(client, params(p, "facet","true", "rows","0", "noexist","noexist_ss", "cat_s","cat_ss", "where_s","where_ss", "num_d","num_f", "num_i","num_l", "num_is","num_ls", "num_fs", "num_ds", "super_s","super_ss", "val_b","val_b", "date","date_dt", "sparse_s","sparse_ss", "multi_ss","multi_ss") ); // multi-valued strings, method=dv for terms facets doStatsTemplated(client, params(p, "terms", "method:dv,", "rows", "0", "noexist", "noexist_ss", "cat_s", "cat_ss", "where_s", "where_ss", "num_d", "num_f", "num_i", "num_l", "super_s", "super_ss", "val_b", "val_b", "date", "date_dt", "sparse_s", "sparse_ss", "multi_ss", "multi_ss")); // single valued docvalues for strings, and single valued numeric doc values for numeric fields - doStatsTemplated(client, params(p, "rows","0", "noexist","noexist_sd", "cat_s","cat_sd", "where_s","where_sd", "num_d","num_dd", "num_i","num_id", "super_s","super_sd", "val_b","val_b", "date","date_dtd", "sparse_s","sparse_sd" ,"multi_ss","multi_sds") ); + doStatsTemplated(client, params(p, "rows","0", "noexist","noexist_sd", "cat_s","cat_sd", "where_s","where_sd", "num_d","num_dd", "num_i","num_id", "num_is","num_lds", "num_fs","num_dds", "super_s","super_sd", "val_b","val_b", "date","date_dtd", "sparse_s","sparse_sd" ,"multi_ss","multi_sds") ); // multi-valued docvalues FacetFieldProcessorDV.unwrap_singleValued_multiDv = false; // better multi-valued coverage - doStatsTemplated(client, params(p, "rows","0", "noexist","noexist_sds", "cat_s","cat_sds", "where_s","where_sds", "num_d","num_d", "num_i","num_i", "super_s","super_sds", "val_b","val_b", "date","date_dtds", "sparse_s","sparse_sds" ,"multi_ss","multi_sds") ); + doStatsTemplated(client, params(p, "rows","0", "noexist","noexist_sds", "cat_s","cat_sds", "where_s","where_sds", "num_d","num_d", "num_i","num_i", "num_is","num_ids", "num_fs","num_fds", "super_s","super_sds", "val_b","val_b", "date","date_dtds", "sparse_s","sparse_sds" ,"multi_ss","multi_sds") ); // multi-valued docvalues FacetFieldProcessorDV.unwrap_singleValued_multiDv = true; - doStatsTemplated(client, params(p, "rows","0", "noexist","noexist_sds", "cat_s","cat_sds", "where_s","where_sds", "num_d","num_d", "num_i","num_i", "super_s","super_sds", "val_b","val_b", "date","date_dtds", "sparse_s","sparse_sds" ,"multi_ss","multi_sds") ); + doStatsTemplated(client, params(p, "rows","0", "noexist","noexist_sds", "cat_s","cat_sds", "where_s","where_sds", "num_d","num_d", "num_i","num_i", "num_is","num_ids", "num_fs","num_fds", "super_s","super_sds", "val_b","val_b", "date","date_dtds", "sparse_s","sparse_sds" ,"multi_ss","multi_sds") ); } public static void doStatsTemplated(Client client, ModifiableSolrParams p) throws Exception { p.set("Z_num_i", "Z_" + p.get("num_i") ); + if (p.get("num_is") == null) p.add("num_is","num_is"); + if (p.get("num_fs") == null) p.add("num_fs","num_fs"); MacroExpander m = new MacroExpander( p.getMap() ); @@ -369,6 +371,8 @@ public class TestJsonFacets extends SolrTestCaseHS { String where_s = m.expand("${where_s}"); String num_d = m.expand("${num_d}"); String num_i = m.expand("${num_i}"); + String num_is = m.expand("${num_is}"); + String num_fs = m.expand("${num_fs}"); String Z_num_i = m.expand("${Z_num_i}"); String val_b = m.expand("${val_b}"); String date = m.expand("${date}"); @@ -379,17 +383,17 @@ public class TestJsonFacets extends SolrTestCaseHS { client.deleteByQuery("*:*", null); SolrInputDocument doc = - sdoc("id", "1", cat_s, "A", where_s, "NY", num_d, "4", num_i, "2", super_s, "zodiac", date, "2001-01-01T01:01:01Z", val_b, "true", sparse_s, "one"); + sdoc("id", "1", cat_s, "A", where_s, "NY", num_d, "4", num_i, "2", num_is,"2",num_is,"-5", num_fs,"2",num_fs,"-5", super_s, "zodiac", date, "2001-01-01T01:01:01Z", val_b, "true", sparse_s, "one"); client.add(doc, null); client.add(doc, null); client.add(doc, null); // a couple of deleted docs - client.add(sdoc("id", "2", cat_s, "B", where_s, "NJ", num_d, "-9", num_i, "-5", super_s,"superman", date,"2002-02-02T02:02:02Z", val_b, "false" , multi_ss,"a", multi_ss,"b" , Z_num_i, "0"), null); + client.add(sdoc("id", "2", cat_s, "B", where_s, "NJ", num_d, "-9", num_i, "-5", num_is,"3",num_is,"-1", num_fs,"3",num_fs,"-1.5", super_s,"superman", date,"2002-02-02T02:02:02Z", val_b, "false" , multi_ss,"a", multi_ss,"b" , Z_num_i, "0"), null); client.add(sdoc("id", "3"), null); client.commit(); - client.add(sdoc("id", "4", cat_s, "A", where_s, "NJ", num_d, "2", num_i, "3", super_s,"spiderman", date,"2003-03-03T03:03:03Z" , multi_ss, "b", Z_num_i, ""+Integer.MIN_VALUE), null); - client.add(sdoc("id", "5", cat_s, "B", where_s, "NJ", num_d, "11", num_i, "7", super_s,"batman" , date,"2001-02-03T01:02:03Z" ,sparse_s,"two", multi_ss, "a"), null); + client.add(sdoc("id", "4", cat_s, "A", where_s, "NJ", num_d, "2", num_i, "3", num_is,"0",num_is,"3", num_fs,"0", num_fs,"3", super_s,"spiderman", date,"2003-03-03T03:03:03Z" , multi_ss, "b", Z_num_i, ""+Integer.MIN_VALUE), null); + client.add(sdoc("id", "5", cat_s, "B", where_s, "NJ", num_d, "11", num_i, "7", num_is,"0", num_fs,"0", super_s,"batman" , date,"2001-02-03T01:02:03Z" ,sparse_s,"two", multi_ss, "a"), null); client.commit(); - client.add(sdoc("id", "6", cat_s, "B", where_s, "NY", num_d, "-5", num_i, "-5", super_s,"hulk" , date,"2002-03-01T03:02:01Z" , multi_ss, "b", multi_ss, "a", Z_num_i, ""+Integer.MAX_VALUE), null); + client.add(sdoc("id", "6", cat_s, "B", where_s, "NY", num_d, "-5", num_i, "-5", num_is,"-1", num_fs,"-1.5", super_s,"hulk" , date,"2002-03-01T03:02:01Z" , multi_ss, "b", multi_ss, "a", Z_num_i, ""+Integer.MAX_VALUE), null); client.commit(); // test for presence of debugging info @@ -1097,6 +1101,34 @@ public class TestJsonFacets extends SolrTestCaseHS { ); + + // multi-valued integer + client.testJQ(params(p, "q", "*:*" + , "json.facet", "{ " + + " c1:'unique(${num_is})', c2:'hll(${num_is})'" + + ",f1:{${terms} type:terms, field:${num_is} } " + + "}" + ) + , "facets=={ count:6 " + + ", c1:5, c2:5" + + ", f1:{ buckets:[ {val:-1,count:2},{val:0,count:2},{val:3,count:2},{val:-5,count:1},{val:2,count:1} ] } " + + "} " + ); + + // multi-valued float + client.testJQ(params(p, "q", "*:*" + , "json.facet", "{ " + + " c1:'unique(${num_fs})', c2:'hll(${num_fs})'" + + ",f1:{${terms} type:terms, field:${num_fs} } " + + "}" + ) + , "facets=={ count:6 " + + ", c1:5, c2:5" + + ", f1:{ buckets:[ {val:-1.5,count:2},{val:0.0,count:2},{val:3.0,count:2},{val:-5.0,count:1},{val:2.0,count:1} ] } " + + "} " + ); + + }