You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by sa...@apache.org on 2016/11/02 23:59:14 UTC

[17/50] [abbrv] lucene-solr:apiv2: SOLR-9681: add filters to any facet command

SOLR-9681: add filters to any facet command


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

Branch: refs/heads/apiv2
Commit: 650276e14bd85cdd12a77956f2403369ff3465ac
Parents: 2e21511
Author: yonik <yo...@apache.org>
Authored: Sat Oct 29 14:16:27 2016 -0400
Committer: yonik <yo...@apache.org>
Committed: Sat Oct 29 14:54:19 2016 -0400

----------------------------------------------------------------------
 solr/CHANGES.txt                                |  7 ++++
 .../solr/search/facet/FacetProcessor.java       | 35 +++++++++++++++++++-
 .../apache/solr/search/facet/FacetRequest.java  | 13 +++++++-
 .../solr/search/facet/TestJsonFacets.java       | 21 ++++++++++++
 4 files changed, 74 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/650276e1/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index f81ff75..50639ab 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -79,6 +79,13 @@ Jetty 9.3.8.v20160314
 Detailed Change List
 ----------------------
 
+New Features
+----------------------
+* SOLR-9681: FacetModule / JSON Facet API added the ability to add filters directly to
+  any facet command.  The filters are applied after any domain change operations.
+  Example:  { type:terms, field:category, filter:"user:yonik" } 
+  (yonik)
+
 Other Changes
 ----------------------
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/650276e1/solr/core/src/java/org/apache/solr/search/facet/FacetProcessor.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/facet/FacetProcessor.java b/solr/core/src/java/org/apache/solr/search/facet/FacetProcessor.java
index fa26319..e610478 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/FacetProcessor.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/FacetProcessor.java
@@ -50,11 +50,13 @@ public abstract class FacetProcessor<FacetRequestT extends FacetRequest>  {
   FacetContext fcontext;
   FacetRequestT freq;
 
+  DocSet filter;  // additional filters specified by "filter"  // TODO: do these need to be on the context to support recomputing during multi-select?
   LinkedHashMap<String,SlotAcc> accMap;
   SlotAcc[] accs;
   CountSlotAcc countAcc;
 
-  /** factory method for invoking json facet framework as whole */
+  /** factory method for invoking json facet framework as whole.
+   * Note: this is currently only used from SimpleFacets, not from JSON Facet API itself. */
   public static FacetProcessor<?> createProcessor(SolrQueryRequest req,
                                                   Map<String, Object> params, DocSet docs){
     FacetParser parser = new FacetTopParser(req);
@@ -84,7 +86,38 @@ public abstract class FacetProcessor<FacetRequestT extends FacetRequest>  {
   }
 
   public void process() throws IOException {
+    // Check filters... if we do have filters they apply after domain changes.
+    // We still calculate them first because we can use it in a parent->child domain change.
+    handleFilters();
     handleDomainChanges();
+    if (filter != null) {
+      fcontext.base = fcontext.base.intersection( filter );
+    }
+  }
+
+  private void handleFilters() throws IOException {
+    if (freq.filters == null || freq.filters.isEmpty()) return;
+
+    List<Query> qlist = new ArrayList<>(freq.filters.size());
+    // TODO: prevent parsing filters each time!
+    for (Object rawFilter : freq.filters) {
+      Query symbolicFilter;
+      if (rawFilter instanceof String) {
+        QParser parser = null;
+        try {
+          parser = QParser.getParser((String)rawFilter, fcontext.req);
+          symbolicFilter = parser.getQuery();
+        } catch (SyntaxError syntaxError) {
+          throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, syntaxError);
+        }
+      } else {
+        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Bad query (expected a string):" + rawFilter);
+      }
+
+      qlist.add(symbolicFilter);
+    }
+
+    this.filter = fcontext.searcher.getDocSet(qlist);
   }
 
   private void handleDomainChanges() throws IOException {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/650276e1/solr/core/src/java/org/apache/solr/search/facet/FacetRequest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/facet/FacetRequest.java b/solr/core/src/java/org/apache/solr/search/facet/FacetRequest.java
index 40ca686..d3c8722 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/FacetRequest.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/FacetRequest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.solr.search.facet;
 
+import java.util.ArrayList;
 import java.util.EnumSet;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -77,7 +78,7 @@ public abstract class FacetRequest {
 
   protected Map<String,AggValueSource> facetStats;  // per-bucket statistics
   protected Map<String,FacetRequest> subFacets;     // per-bucket sub-facets
-  protected List<String> filters;
+  protected List<Object> filters;
   protected boolean processEmpty;
   protected Domain domain;
 
@@ -376,6 +377,16 @@ abstract class FacetParser<FacetRequestT extends FacetRequest> {
 
       }
 
+      Object filterOrList = m.get("filter");
+      if (filterOrList != null) {
+        if (filterOrList instanceof List) {
+          facet.filters = (List<Object>)filterOrList;
+        } else {
+          facet.filters = new ArrayList<>(1);
+          facet.filters.add(filterOrList);
+        }
+      }
+
     }
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/650276e1/solr/core/src/test/org/apache/solr/search/facet/TestJsonFacets.java
----------------------------------------------------------------------
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 5527a3d..eafa134 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
@@ -1164,6 +1164,27 @@ public class TestJsonFacets extends SolrTestCaseHS {
     );
 
 
+    // test filter
+    client.testJQ(params(p, "q", "*:*", "myfilt","${cat_s}:A"
+        , "json.facet", "{" +
+            "t:{${terms} type:terms, field:${cat_s}, filter:[]}" + // empty filter list
+            ",t_filt:{${terms} type:terms, field:${cat_s}, filter:'${cat_s}:B'}" +
+            ",t_filt2:{${terms} type:terms, field:${cat_s}, filter:'{!query v=$myfilt}'}" +  // test access to qparser and other query parameters
+            ",t_filt3:{${terms} type:terms, field:${cat_s}, filter:['-id:1','-id:2']}" +
+            ",q:{type:query, q:'${cat_s}:B', filter:['-id:5']}" + // also tests a top-level negative filter
+            ",r:{type:range, field:${num_d}, start:-5, end:10, gap:5, filter:'-id:4'}" +
+            "}"
+        )
+        , "facets=={ count:6, " +
+            "t       :{ buckets:[ {val:B, count:3}, {val:A, count:2} ] }" +
+            ",t_filt :{ buckets:[ {val:B, count:3}] } " +
+            ",t_filt2:{ buckets:[ {val:A, count:2}] } " +
+            ",t_filt3:{ buckets:[ {val:B, count:2}, {val:A, count:1}] } " +
+            ",q:{count:2}" +
+            ",r:{buckets:[ {val:-5.0,count:1}, {val:0.0,count:1}, {val:5.0,count:0} ] }" +
+            "}"
+    );
+    
   }
 
   @Test