You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by sh...@apache.org on 2017/04/01 11:17:05 UTC

[7/9] lucene-solr:feature/autoscaling: SOLR-7452: refinement of missing buckets and partial facets through missing buckets

SOLR-7452: refinement of missing buckets and partial facets through missing buckets


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/6edef462
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/6edef462
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/6edef462

Branch: refs/heads/feature/autoscaling
Commit: 6edef4625e11099cc5ea0a2ec1eda152b914769f
Parents: 30dc73a
Author: yonik <yo...@apache.org>
Authored: Thu Mar 30 12:55:27 2017 -0400
Committer: Shalin Shekhar Mangar <sh...@apache.org>
Committed: Sat Apr 1 16:46:45 2017 +0530

----------------------------------------------------------------------
 .../solr/search/facet/FacetFieldMerger.java     | 25 +++++++++++++++++++
 .../solr/search/facet/FacetFieldProcessor.java  | 14 +++++++++++
 .../search/facet/FacetRequestSortedMerger.java  |  8 ++++++
 .../search/facet/TestJsonFacetRefinement.java   | 26 +++++++++++++++++++-
 4 files changed, 72 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6edef462/solr/core/src/java/org/apache/solr/search/facet/FacetFieldMerger.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/facet/FacetFieldMerger.java b/solr/core/src/java/org/apache/solr/search/facet/FacetFieldMerger.java
index 63e8743..f8f6463 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/FacetFieldMerger.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/FacetFieldMerger.java
@@ -18,8 +18,11 @@
 package org.apache.solr.search.facet;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import org.apache.solr.common.util.SimpleOrderedMap;
@@ -167,7 +170,29 @@ public class FacetFieldMerger extends FacetRequestSortedMerger<FacetField> {
     // basically , only do at the top-level facet?
   }
 
+  @Override
+  Map<String, Object> getRefinementSpecial(Context mcontext, Map<String, Object> refinement, Collection<String> tagsWithPartial) {
+    if (!tagsWithPartial.isEmpty()) {
+      // Since special buckets missing and allBuckets themselves will always be included, we only need to worry about subfacets being partial.
+      if (freq.missing) {
+        refinement = getRefinementSpecial(mcontext, refinement, tagsWithPartial, missingBucket, "missing");
+      }
+      if (freq.allBuckets) {
+        refinement = getRefinementSpecial(mcontext, refinement, tagsWithPartial, allBuckets, "allBuckets");
+      }
+    }
+    return refinement;
+  }
 
+  private Map<String, Object> getRefinementSpecial(Context mcontext, Map<String, Object> refinement, Collection<String> tagsWithPartial, FacetBucket bucket, String label) {
+    // boolean prev = mcontext.setBucketWasMissing(true); // the special buckets should have the same "missing" status as this facet, so no need to set it again
+    Map<String, Object> bucketRefinement = bucket.getRefinement(mcontext, tagsWithPartial);
+    if (bucketRefinement != null) {
+      refinement = refinement == null ? new HashMap<>(2) : refinement;
+      refinement.put(label, bucketRefinement);
+    }
+    return refinement;
+  }
 
   private static class FacetNumBucketsMerger extends FacetMerger {
     long sumBuckets;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6edef462/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessor.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessor.java b/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessor.java
index a29e78d..d4daf08 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessor.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessor.java
@@ -36,6 +36,8 @@ import org.apache.solr.schema.FieldType;
 import org.apache.solr.schema.SchemaField;
 import org.apache.solr.search.DocSet;
 
+import static org.apache.solr.search.facet.FacetContext.SKIP_FACET;
+
 /**
  * Facet processing based on field values. (not range nor by query)
  * @see FacetField
@@ -528,6 +530,9 @@ abstract class FacetFieldProcessor extends FacetProcessor<FacetField> {
   }
 
   protected SimpleOrderedMap<Object> refineFacets() throws IOException {
+    boolean skipThisFacet = (fcontext.flags & SKIP_FACET) != 0;
+
+
     List leaves = asList(fcontext.facetInfo.get("_l"));        // We have not seen this bucket: do full faceting for this bucket, including all sub-facets
     List<List> skip = asList(fcontext.facetInfo.get("_s"));    // We have seen this bucket, so skip stats on it, and skip sub-facets except for the specified sub-facets that should calculate specified buckets.
     List<List> partial = asList(fcontext.facetInfo.get("_p")); // We have not seen this bucket, do full faceting for this bucket, and most sub-facets... but some sub-facets are partial and should only visit specified buckets.
@@ -563,6 +568,15 @@ abstract class FacetFieldProcessor extends FacetProcessor<FacetField> {
       bucketList.add( refineBucket(bucketVal, false, facetInfo ) );
     }
 
+    if (freq.missing) {
+      Map<String,Object> bucketFacetInfo = (Map<String,Object>)fcontext.facetInfo.get("missing");
+
+      if (bucketFacetInfo != null || !skipThisFacet) {
+        SimpleOrderedMap<Object> missingBucket = new SimpleOrderedMap<>();
+        fillBucket(missingBucket, getFieldMissingQuery(fcontext.searcher, freq.field), null, skipThisFacet, bucketFacetInfo);
+        res.add("missing", missingBucket);
+      }
+    }
 
     // If there are just a couple of leaves, and if the domain is large, then
     // going by term is likely the most efficient?

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6edef462/solr/core/src/java/org/apache/solr/search/facet/FacetRequestSortedMerger.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/facet/FacetRequestSortedMerger.java b/solr/core/src/java/org/apache/solr/search/facet/FacetRequestSortedMerger.java
index e05064c..9ffdea7 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/FacetRequestSortedMerger.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/FacetRequestSortedMerger.java
@@ -240,6 +240,14 @@ abstract class FacetRequestSortedMerger<FacetRequestT extends FacetRequestSorted
       if (skipBuckets != null) refinement.put("_s", skipBuckets);
     }
 
+    refinement = getRefinementSpecial(mcontext, refinement, tagsWithPartial);
+
+    return refinement;
+  }
+
+  // utility method for subclasses to override to finish calculating faceting (special buckets in field facets)... this feels hacky and we
+  // should find a better way.
+  Map<String,Object> getRefinementSpecial(Context mcontext, Map<String,Object> refinement, Collection<String> tagsWithPartial) {
     return refinement;
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/6edef462/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacetRefinement.java
----------------------------------------------------------------------
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 b4b0220..52b8be4 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
@@ -219,6 +219,17 @@ public class TestJsonFacetRefinement extends SolrTestCaseHS {
             "}"
     );
 
+    // test partial _p under a missing bucket
+    doTestRefine("{top:{type:terms, field:Afield, refine:true, limit:1, missing:true, facet:{x : {type:terms, field:X, limit:1, refine:true} } } }",
+        "{top: {buckets:[], missing:{count:12, x:{buckets:[{val:x2, count:4},{val:x3, count:2}]} }  } }",
+        "{top: {buckets:[], missing:{count:10, x:{buckets:[{val:x1, count:5},{val:x4, count:3}]} }  } }",
+        "=={top: {" +
+            "missing:{x:{_l:[x1]}}" +
+            "    }  " +
+            "}"
+        , null
+    );
+
   }
 
 
@@ -266,6 +277,17 @@ public class TestJsonFacetRefinement extends SolrTestCaseHS {
     );
     ****/
 
+    // test refining under the special "missing" bucket of a field facet
+    client.testJQ(params(p, "q", "*:*",
+        "json.facet", "{" +
+            "f:{type:terms, field:missing_s, limit:1, overrequest:0, missing:true, refine:true,  facet:{  cat:{type:terms, field:${cat_s}, limit:1, overrequest:0, refine:true   }  }}" +
+            "}"
+        )
+        , "facets=={ count:8" +
+            ", f:{ buckets:[], missing:{count:8, cat:{buckets:[{val:A,count:4}]}  }  }" +  // just like the previous response, just nested under a field facet
+            "}"
+    );
+
 
     client.testJQ(params(p, "q", "*:*",
         "json.facet", "{" +
@@ -317,7 +339,7 @@ public class TestJsonFacetRefinement extends SolrTestCaseHS {
             "}"
     );
 
-    // test missing buckets (field facet within field facet)
+    // test partial buckets (field facet within field facet)
     client.testJQ(params(p, "q", "*:*",
         "json.facet", "{" +
             "ab:{type:terms, field:${cat_s}, limit:1, overrequest:0, refine:true,  facet:{  xy:{type:terms, field:${xy_s}, limit:1, overrequest:0, refine:true   }  }}" +
@@ -345,6 +367,8 @@ public class TestJsonFacetRefinement extends SolrTestCaseHS {
             "}"
     );
 
+
+
   }