mirror of https://github.com/apache/lucene.git
SOLR-9681: add filters to any facet command
This commit is contained in:
parent
2e21511cd3
commit
650276e14b
|
@ -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
|
||||
----------------------
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue