From 0f8802ba20de35daac75f6bbcc28a1789a27b06a Mon Sep 17 00:00:00 2001 From: yonik Date: Sat, 29 Oct 2016 20:43:54 -0400 Subject: [PATCH] SOLR-9704: optimization: use filters after blockChildren for acceptDocs --- solr/CHANGES.txt | 5 +++ .../solr/search/facet/FacetProcessor.java | 34 ++++++++++++------- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 50639ab6dfc..3b3fba7dd3d 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -86,6 +86,11 @@ New Features Example: { type:terms, field:category, filter:"user:yonik" } (yonik) +Optimizations +---------------------- +* SOLR-9704: Facet Module / JSON Facet API: Optimize blockChildren facets that have + filters specified by using those filters as acceptDocs. (yonik) + Other Changes ---------------------- 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 e6104782c08..a8914f1dc83 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 @@ -28,7 +28,6 @@ import java.util.Map; import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.BooleanQuery; -import org.apache.lucene.search.MatchAllDocsQuery; import org.apache.lucene.search.Query; import org.apache.solr.common.SolrException; import org.apache.solr.common.util.SimpleOrderedMap; @@ -88,14 +87,14 @@ public abstract class FacetProcessor { 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) { + evalFilters(); + boolean appliedFilters = handleDomainChanges(); + if (filter != null && !appliedFilters) { fcontext.base = fcontext.base.intersection( filter ); } } - private void handleFilters() throws IOException { + private void evalFilters() throws IOException { if (freq.filters == null || freq.filters.isEmpty()) return; List qlist = new ArrayList<>(freq.filters.size()); @@ -120,10 +119,11 @@ public abstract class FacetProcessor { this.filter = fcontext.searcher.getDocSet(qlist); } - private void handleDomainChanges() throws IOException { - if (freq.domain == null) return; + private boolean handleDomainChanges() throws IOException { + if (freq.domain == null) return false; handleFilterExclusions(); - handleBlockJoin(); + boolean appliedFilters = handleBlockJoin(); + return appliedFilters; } private void handleFilterExclusions() throws IOException { @@ -187,8 +187,10 @@ public abstract class FacetProcessor { fcontext.base = fcontext.searcher.getDocSet(qlist); } - private void handleBlockJoin() throws IOException { - if (!(freq.domain.toChildren || freq.domain.toParent)) return; + // returns "true" if filters have already been applied. + private boolean handleBlockJoin() throws IOException { + boolean appliedFilters = false; + if (!(freq.domain.toChildren || freq.domain.toParent)) return appliedFilters; // TODO: avoid query parsing per-bucket somehow... String parentStr = freq.domain.parents; @@ -205,13 +207,21 @@ public abstract class FacetProcessor { DocSet result; if (freq.domain.toChildren) { - DocSet filt = fcontext.searcher.getDocSetBits( new MatchAllDocsQuery() ); - result = BlockJoin.toChildren(input, parents, filt, fcontext.qcontext); + // If there are filters on this facet, then use them as acceptDocs when executing toChildren. + // We need to remember to not redundantly re-apply these filters after. + DocSet acceptDocs = this.filter; + if (acceptDocs == null) { + acceptDocs = fcontext.searcher.getLiveDocs(); + } else { + appliedFilters = true; + } + result = BlockJoin.toChildren(input, parents, acceptDocs, fcontext.qcontext); } else { result = BlockJoin.toParents(input, parents, fcontext.qcontext); } fcontext.base = result; + return appliedFilters; } protected void processStats(SimpleOrderedMap bucket, DocSet docs, int docCount) throws IOException {