You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by ds...@apache.org on 2021/06/09 04:14:53 UTC

[solr] branch main updated: SOLR-15457: Faceting on EnumFieldType was returning ordinals. (#2508)

This is an automated email from the ASF dual-hosted git repository.

dsmiley pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git


The following commit(s) were added to refs/heads/main by this push:
     new 96d0718  SOLR-15457: Faceting on EnumFieldType was returning ordinals. (#2508)
96d0718 is described below

commit 96d071892f611ccbaa7b0272eb11327d6ebc1dec
Author: Thomas Wöckinger <th...@users.noreply.github.com>
AuthorDate: Tue Jun 8 23:41:49 2021 -0400

    SOLR-15457: Faceting on EnumFieldType was returning ordinals. (#2508)
    
    Fix JSON Faceting on EnumFieldType -- returned values should not be internal ordinals.
    This is a regression introduced in 8.7.
    
    Co-authored-by: Thomas Wöckinger <tw...@silbergrau.com>
---
 solr/CHANGES.txt                                   |  5 ++-
 .../solr/search/facet/FacetRangeProcessor.java     | 46 ++++++++++++++--------
 .../test/org/apache/solr/schema/EnumFieldTest.java | 21 +++++++++-
 3 files changed, 53 insertions(+), 19 deletions(-)

diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 9d72c0d..f60c979 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -426,7 +426,10 @@ Bug Fixes
   (David Smiley)
 
 * SOLR-15191: Fix JSON Faceting on EnumFieldType if allBuckets, numBuckets or missing is set.
-  (Thomas Wöckinger, David Smiley)
+  (Thomas Wöckinger via David Smiley)
+
+* SOLR-15457: Fix JSON Faceting on EnumFieldType -- returned values should not be internal ordinals.
+  (Thomas Wöckinger via David Smiley)
 
 * SOLR-15273: Fix NullPointerException in StoredFieldsShardResponseProcessor that happened when a field name alias is
   used for the unique key field in searches with distributed result grouping. (limingnihao via Christine Poerschke)
diff --git a/solr/core/src/java/org/apache/solr/search/facet/FacetRangeProcessor.java b/solr/core/src/java/org/apache/solr/search/facet/FacetRangeProcessor.java
index fdb6496..6885ae7 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/FacetRangeProcessor.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/FacetRangeProcessor.java
@@ -20,10 +20,12 @@ package org.apache.solr.search.facet;
 
 import org.apache.lucene.search.Query;
 import org.apache.lucene.util.NumericUtils;
+import org.apache.solr.common.EnumFieldValue;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.FacetParams;
 import org.apache.solr.common.util.SimpleOrderedMap;
 import org.apache.solr.schema.*;
+import org.apache.solr.schema.AbstractEnumField.EnumMapping;
 import org.apache.solr.search.DocSet;
 import org.apache.solr.search.ExtendedQuery;
 import org.apache.solr.search.SyntaxError;
@@ -146,6 +148,9 @@ class FacetRangeProcessor extends FacetProcessor<FacetRange> {
     final FieldType ft = sf.getType();
 
     if (ft.getNumberType() != null) {
+      if (ft instanceof AbstractEnumField) {
+        return new EnumCalc(sf);
+      } 
       switch (ft.getNumberType()) {
         case FLOAT:
           return new FloatCalc(sf);
@@ -171,22 +176,7 @@ class FacetRangeProcessor extends FacetProcessor<FacetRange> {
   private static Calc getCalcForField(SchemaField sf) {
     final FieldType ft = sf.getType();
     if (ft instanceof TrieField || ft.isPointField()) {
-      switch (ft.getNumberType()) {
-        case FLOAT:
-          return new FloatCalc(sf);
-        case DOUBLE:
-          return new DoubleCalc(sf);
-        case INTEGER:
-          return new IntCalc(sf);
-        case LONG:
-          return new LongCalc(sf);
-        case DATE:
-          return new DateCalc(sf, null);
-        default:
-          throw new SolrException
-              (SolrException.ErrorCode.BAD_REQUEST,
-                  "Unable to range facet on numeric field of unexpected type:" + sf.getName());
-      }
+      return getNumericCalc(sf);
     } else if (ft instanceof CurrencyFieldType) {
       return new CurrencyCalc(sf);
     } else if (ft instanceof DateRangeField) {
@@ -199,7 +189,7 @@ class FacetRangeProcessor extends FacetProcessor<FacetRange> {
   }
 
   @SuppressWarnings({"unchecked", "rawtypes"})
-  private void createRangeList() throws IOException {
+  private void createRangeList() {
 
     rangeList = new ArrayList<>();
     otherList = new ArrayList<>(3);
@@ -773,6 +763,28 @@ class FacetRangeProcessor extends FacetProcessor<FacetRange> {
     }
   }
 
+  private static class EnumCalc extends Calc {
+
+    private final EnumMapping mapping;
+    public EnumCalc(final SchemaField f) {
+      super(f);
+      mapping = ((AbstractEnumField)field.getType()).getEnumMapping();
+    }
+    @Override
+    public EnumFieldValue bitsToValue(long bits) {
+      Integer val = (int)bits;
+      return new EnumFieldValue(val, mapping.intValueToStringValue(val));
+    }
+    @Override
+    protected EnumFieldValue parseStr(String rawval) {
+      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Cannot perform range faceting over Enum fields!");
+    }
+    @Override
+    protected EnumFieldValue parseAndAddGap(@SuppressWarnings("rawtypes") Comparable value, String gap) {
+      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Cannot perform range faceting over Enum fields!");
+    }
+  }
+
   private static class DateCalc extends Calc {
     private final Date now;
     public DateCalc(final SchemaField f,
diff --git a/solr/core/src/test/org/apache/solr/schema/EnumFieldTest.java b/solr/core/src/test/org/apache/solr/schema/EnumFieldTest.java
index 4a34930..9520034 100644
--- a/solr/core/src/test/org/apache/solr/schema/EnumFieldTest.java
+++ b/solr/core/src/test/org/apache/solr/schema/EnumFieldTest.java
@@ -18,13 +18,18 @@ package org.apache.solr.schema;
 
 import java.util.Arrays;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.common.EnumFieldValue;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.SolrQueryResponse;
 import org.apache.solr.search.SolrQueryParser;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -571,6 +576,7 @@ public class EnumFieldTest extends SolrTestCaseJ4 {
     }
   }
   
+  @SuppressWarnings("unchecked")
   @Test
   public void testFacetEnumSearch() throws Exception {
     assumeFalse("This requires docValues",
@@ -592,6 +598,19 @@ public class EnumFieldTest extends SolrTestCaseJ4 {
 
     assertQ(req("fl", "" + FIELD_NAME, "q", FIELD_NAME + ":*", "json.facet", jsonFacetParam),
         "//*[@name='facets']/long/text()=6",
-        "//*[@name='allBuckets']/long/text()=6");
+        "//*[@name='allBuckets']/long/text()=6",
+        "//*[@name='buckets']/lst[int[@name='count'][.='2']][str[@name='val'][.='Critical']]",
+        "//*[@name='buckets']/lst[int[@name='count'][.='1']][str[@name='val'][.='Not Available']]",
+        "//*[@name='buckets']/lst[int[@name='count'][.='1']][str[@name='val'][.='Low']]",
+        "//*[@name='buckets']/lst[int[@name='count'][.='1']][str[@name='val'][.='Medium']]",
+        "//*[@name='buckets']/lst[int[@name='count'][.='1']][str[@name='val'][.='High']]");
+
+    try (SolrQueryRequest req = req("fl", "" + FIELD_NAME, "q", FIELD_NAME + ":*", "json.facet", jsonFacetParam, "wt", "json")) {
+      SolrQueryResponse rsp = h.queryAndResponse(req.getParams().get(CommonParams.QT),req);
+      List<NamedList<?>> buckets = (List<NamedList<?>>) ((NamedList<?>)((NamedList<?>)rsp.getValues().get("facets")).get("severity")).get("buckets");
+      for (NamedList<?> bucket : buckets) {
+        assertTrue("Bucket value must be instance of EnumFieldVale!", bucket.get("val") instanceof EnumFieldValue);
+      }
+    }
   }
 }