You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ho...@apache.org on 2020/06/03 16:10:04 UTC

[lucene-solr] branch master updated: SOLR-14520: Fixed server errors from the json.facet allBuckets:true option when combined with refine:true

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

hossman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git


The following commit(s) were added to refs/heads/master by this push:
     new fb58f43  SOLR-14520: Fixed server errors from the json.facet allBuckets:true option when combined with refine:true
fb58f43 is described below

commit fb58f433fbed8f961bce88961084202428ef287a
Author: Chris Hostetter <ho...@apache.org>
AuthorDate: Wed Jun 3 09:09:46 2020 -0700

    SOLR-14520: Fixed server errors from the json.facet allBuckets:true option when combined with refine:true
---
 solr/CHANGES.txt                                   |  2 +
 .../search/facet/FacetFieldProcessorByArray.java   |  4 ++
 .../java/org/apache/solr/search/facet/SlotAcc.java | 57 ++++++++++++++++++++++
 .../solr/search/facet/TestJsonFacetRefinement.java | 19 +++++---
 4 files changed, 76 insertions(+), 6 deletions(-)

diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 97a00f2..577b214 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -209,6 +209,8 @@ Bug Fixes
 
 * SOLR-14525: SolrCoreAware, ResourceLoaderAware should be honored for plugin loaded from packages (noble)
 
+* SOLR-14520: Fixed server errors from the json.facet allBuckets:true option when combined with refine:true
+  (Michael Gibney, hossman)
 
 Other Changes
 ---------------------
diff --git a/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessorByArray.java b/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessorByArray.java
index 318dbc7..dff72b4 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessorByArray.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessorByArray.java
@@ -85,7 +85,11 @@ abstract class FacetFieldProcessorByArray extends FacetFieldProcessor {
 
     if (refineResult != null) {
       if (freq.allBuckets) {
+        // count is irrelevant, but hardcoded in collect(...), so intercept/mask normal counts.
+        // Set here to prevent createAccs(...) from creating a 1-slot countAcc that will fail with AIOOBE
+        countAcc = SlotAcc.DEV_NULL_SLOT_ACC;
         createAccs(nDocs, 1);
+        otherAccs = accs; // accs is created above and set on allBucketsAcc; but during collection, setNextReader is called on otherAccs.
         allBucketsAcc = new SpecialSlotAcc(fcontext, null, -1, accs, 0);
         collectDocs();
 
diff --git a/solr/core/src/java/org/apache/solr/search/facet/SlotAcc.java b/solr/core/src/java/org/apache/solr/search/facet/SlotAcc.java
index 2ab93cc..522c8b4 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/SlotAcc.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/SlotAcc.java
@@ -595,6 +595,63 @@ public abstract class SlotAcc implements Closeable {
     public abstract long getCount(int slot);
   }
 
+  /**
+   * This CountSlotAcc exists as a /dev/null sink for callers of collect(...) and other "write"-type
+   * methods. It should be used in contexts where "read"-type access methods will never be called.
+   */
+  static final CountSlotAcc DEV_NULL_SLOT_ACC = new CountSlotAcc(null) {
+
+    @Override
+    public void resize(Resizer resizer) {
+      // No-op
+    }
+
+    @Override
+    public void reset() throws IOException {
+      // No-op
+    }
+
+    @Override
+    public void collect(int doc, int slot, IntFunction<SlotContext> slotContext) throws IOException {
+      // No-op
+    }
+
+    @Override
+    public void incrementCount(int slot, long count) {
+      // No-op
+    }
+
+    @Override
+    public void setNextReader(LeafReaderContext readerContext) throws IOException {
+      // No-op
+    }
+
+    @Override
+    public int collect(DocSet docs, int slot, IntFunction<SlotContext> slotContext) throws IOException {
+      return docs.size(); // dressed up no-op
+    }
+
+    @Override
+    public Object getValue(int slotNum) throws IOException {
+      throw new UnsupportedOperationException("not supported");
+    }
+
+    @Override
+    public int compare(int slotA, int slotB) {
+      throw new UnsupportedOperationException("not supported");
+    }
+
+    @Override
+    public void setValues(SimpleOrderedMap<Object> bucket, int slotNum) throws IOException {
+      throw new UnsupportedOperationException("not supported");
+    }
+
+    @Override
+    public long getCount(int slot) {
+      throw new UnsupportedOperationException("not supported");
+    }
+  };
+
   static class CountSlotArrAcc extends CountSlotAcc {
     long[] result;
 
diff --git a/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacetRefinement.java b/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacetRefinement.java
index 522b22c..ed7ded1 100644
--- a/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacetRefinement.java
+++ b/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacetRefinement.java
@@ -1082,7 +1082,7 @@ public class TestJsonFacetRefinement extends SolrTestCaseHS {
      , "facets=={foo:555}"
      );
      ****/
-    for (String method : new String[]{"","dvhash","stream","uif","enum","stream","smart"}) {
+    for (String method : new String[]{"","dv", "dvhash","stream","uif","enum","stream","smart"}) {
       if (method.equals("")) {
         p.remove("terms");
       } else {
@@ -1362,17 +1362,24 @@ public class TestJsonFacetRefinement extends SolrTestCaseHS {
       );
 
       // test filling in missing "allBuckets"
-      client.testJQ(params(p, "q", "*:*",
+      client.testJQ(params(p, "q", "*:*", 
           "json.facet", "{" +
-              "  cat :{${terms} type:terms, field:${cat_s}, limit:1, overrequest:0, refine:false, allBuckets:true, facet:{  xy:{${terms} type:terms, field:${xy_s}, limit:1, overrequest:0, allBuckets:true, refine:false}  }  }" +
+              "  cat0:{${terms} type:terms, field:${cat_s}, limit:1, overrequest:0, refine:false, allBuckets:true, facet:{  xy:{${terms} type:terms, field:${xy_s}, limit:1, overrequest:0, allBuckets:true, refine:false}  }  }" +
+              ", cat1:{${terms} type:terms, field:${cat_s}, limit:1, overrequest:0, refine:true, allBuckets:true, sort:'min asc', facet:{  min:'min(${num_d})' }  }" +
               ", cat2:{${terms} type:terms, field:${cat_s}, limit:1, overrequest:0, refine:true , allBuckets:true, facet:{  xy:{${terms} type:terms, field:${xy_s}, limit:1, overrequest:0, allBuckets:true, refine:true }  }  }" +
-              ", cat3:{${terms} type:terms, field:${cat_s}, limit:1, overrequest:0, refine:true , allBuckets:true, facet:{  xy:{${terms} type:terms, field:${xy_s}, limit:1, overrequest:0, allBuckets:true, refine:true , facet:{f:'sum(${num_d})'}   }  }  }" +
+              ", cat3:{${terms} type:terms, field:${cat_s}, limit:1, overrequest:0, refine:true , allBuckets:true, facet:{  xy:{${terms} type:terms, field:${xy_s}, limit:1, overrequest:0, allBuckets:true, refine:true , facet:{sum:'sum(${num_d})'}   }  }  }" +
+              ", cat4:{${terms} type:terms, field:${cat_s}, limit:1, overrequest:0, refine:true , allBuckets:true, facet:{  xy:{${terms} type:terms, field:${xy_s}, limit:1, overrequest:0, allBuckets:true, refine:true , sort:'sum asc', facet:{sum:'sum(${num_d})'}   }  }  }" +
+              // using overrefine only so we aren't fooled by 'local maximum' and ask all shards for 'B'
+              ", cat5:{${terms} type:terms, field:${cat_s}, limit:1, overrequest:0, refine:true, overrefine:2, allBuckets:true,  sort:'min desc' facet:{  min:'min(${num_d})', xy:{${terms} type:terms, field:${xy_s}, limit:1, overrequest:0, allBuckets:true, refine:true, facet:{sum:'sum(${num_d})'}   }  }  }" +
               "}"
           )
           , "facets=={ count:8" +
-              ", cat:{ allBuckets:{count:8}, buckets:[  {val:A, count:3, xy:{buckets:[{count:2, val:X}], allBuckets:{count:3}}}]  }" +
+              ",cat0:{ allBuckets:{count:8}, buckets:[  {val:A, count:3, xy:{buckets:[{count:2, val:X}], allBuckets:{count:3}}}]  }" +
+              ",cat1:{ allBuckets:{count:8, min:-19.0 }, buckets:[  {val:A, count:4, min:-19.0 }]  }" +
               ",cat2:{ allBuckets:{count:8}, buckets:[  {val:A, count:4, xy:{buckets:[{count:3, val:X}], allBuckets:{count:4}}}]  }" +
-              ",cat3:{ allBuckets:{count:8}, buckets:[  {val:A, count:4, xy:{buckets:[{count:3, val:X, f:23.0}], allBuckets:{count:4, f:4.0}}}]  }" +
+              ",cat3:{ allBuckets:{count:8}, buckets:[  {val:A, count:4, xy:{buckets:[{count:3, val:X, sum:23.0}], allBuckets:{count:4, sum:4.0}}}]  }" +
+              ",cat4:{ allBuckets:{count:8}, buckets:[  {val:A, count:4, xy:{buckets:[{count:1, val:Y, sum:-19.0}], allBuckets:{count:4, sum:4.0}}}]  }" +
+              ",cat5:{ allBuckets:{count:8, min:-19.0 }, buckets:[  {val:B, count:4, min:-11.0, xy:{buckets:[{count:2, val:X, sum:6.0}], allBuckets:{count:4, sum:-2.0}}}]  }" +
               "}"
       );