| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.solr.request; |
| |
| import java.lang.invoke.MethodHandles; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.Date; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| |
| import org.apache.solr.SolrTestCaseJ4; |
| import org.apache.solr.common.SolrException; |
| import org.apache.solr.common.SolrException.ErrorCode; |
| import org.apache.solr.common.params.FacetParams; |
| import org.apache.solr.common.params.FacetParams.FacetRangeInclude; |
| import org.apache.solr.common.params.FacetParams.FacetRangeMethod; |
| import org.apache.solr.common.params.FacetParams.FacetRangeOther; |
| import org.apache.solr.common.params.ModifiableSolrParams; |
| import org.apache.solr.common.params.SolrParams; |
| import org.apache.solr.common.util.NamedList; |
| import org.apache.solr.response.SolrQueryResponse; |
| import org.apache.solr.schema.NumberType; |
| import org.apache.solr.schema.SchemaField; |
| import org.apache.solr.util.TimeZoneUtils; |
| import org.junit.BeforeClass; |
| import org.junit.Test; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import static org.apache.solr.common.util.Utils.fromJSONString; |
| |
| |
| public class SimpleFacetsTest extends SolrTestCaseJ4 { |
| |
| private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); |
| |
| @BeforeClass |
| public static void beforeClass() throws Exception { |
| // we need DVs on point fields to compute stats & facets |
| if (Boolean.getBoolean(NUMERIC_POINTS_SYSPROP)) System.setProperty(NUMERIC_DOCVALUES_SYSPROP,"true"); |
| initCore("solrconfig.xml","schema.xml"); |
| createIndex(); |
| } |
| |
| static int random_commit_percent = 30; |
| static int random_dupe_percent = 25; // some duplicates in the index to create deleted docs |
| |
| static void randomCommit(int percent_chance) { |
| if (random().nextInt(100) <= percent_chance) |
| assertU(commit()); |
| } |
| |
| static ArrayList<String[]> pendingDocs = new ArrayList<>(); |
| |
| // committing randomly gives different looking segments each time |
| static void add_doc(String... fieldsAndValues) { |
| do { |
| //do our own copy-field: |
| List<String> fieldsAndValuesList = new ArrayList<>(Arrays.asList(fieldsAndValues)); |
| int idx = fieldsAndValuesList.indexOf("a_tdt"); |
| if (idx >= 0) { |
| fieldsAndValuesList.add("a_drf"); |
| fieldsAndValuesList.add(fieldsAndValuesList.get(idx + 1));//copy |
| } |
| idx = fieldsAndValuesList.indexOf("bday"); |
| if (idx >= 0) { |
| fieldsAndValuesList.add("bday_drf"); |
| fieldsAndValuesList.add(fieldsAndValuesList.get(idx + 1));//copy |
| } |
| fieldsAndValues = fieldsAndValuesList.toArray(new String[fieldsAndValuesList.size()]); |
| |
| pendingDocs.add(fieldsAndValues); |
| } while (random().nextInt(100) <= random_dupe_percent); |
| |
| // assertU(adoc(fieldsAndValues)); |
| // randomCommit(random_commit_percent); |
| } |
| |
| |
| static void createIndex() throws Exception { |
| doEmptyFacetCounts(); // try on empty index |
| |
| indexSimpleFacetCounts(); |
| indexDateFacets(); |
| indexFacetSingleValued(); |
| indexFacetPrefixMultiValued(); |
| indexFacetPrefixSingleValued(); |
| indexFacetContains(); |
| indexSimpleGroupedFacetCounts(); |
| |
| Collections.shuffle(pendingDocs, random()); |
| for (String[] doc : pendingDocs) { |
| assertU(adoc(doc)); |
| randomCommit(random_commit_percent); |
| } |
| assertU(commit()); |
| } |
| |
| static void indexSimpleFacetCounts() { |
| add_doc("id", "42", |
| "range_facet_f", "35.3", |
| "range_facet_f1", "35.3", |
| "trait_s", "Tool", "trait_s", "Obnoxious", |
| "name", "Zapp Brannigan", |
| "foo_s","A", "foo_s","B", |
| "range_facet_mv_f", "1.0", |
| "range_facet_mv_f", "2.5", |
| "range_facet_mv_f", "3.7", |
| "range_facet_mv_f", "3.3" |
| ); |
| add_doc("id", "43" , |
| "range_facet_f", "28.789", |
| "range_facet_f1", "28.789", |
| "title", "Democratic Order of Planets", |
| "foo_s","A", "foo_s","B", |
| "range_facet_mv_f", "3.0", |
| "range_facet_mv_f", "7.5", |
| "range_facet_mv_f", "12.0" |
| ); |
| add_doc("id", "44", |
| "range_facet_f", "15.97", |
| "range_facet_f1", "15.97", |
| "trait_s", "Tool", |
| "name", "The Zapper", |
| "foo_s","A", "foo_s","B", "foo_s","C", |
| "range_facet_mv_f", "0.0", |
| "range_facet_mv_f", "5", |
| "range_facet_mv_f", "74" |
| ); |
| add_doc("id", "45", |
| "range_facet_f", "30.0", |
| "range_facet_f1", "30.0", |
| "trait_s", "Chauvinist", |
| "title", "25 star General", |
| "foo_s","A", "foo_s","B", |
| "range_facet_mv_f_f", "12.0", |
| "range_facet_mv_f", "212.452", |
| "range_facet_mv_f", "32.77", |
| "range_facet_mv_f", "0.123" |
| ); |
| add_doc("id", "46", |
| "range_facet_f", "20.0", |
| "range_facet_f1", "20.0", |
| "trait_s", "Obnoxious", |
| "subject", "Defeated the pacifists of the Gandhi nebula", |
| "foo_s","A", "foo_s","B", |
| "range_facet_mv_f", "123.0", |
| "range_facet_mv_f", "2.0", |
| "range_facet_mv_f", "7.3", |
| "range_facet_mv_f", "0.123" |
| ); |
| add_doc("id", "47", |
| "range_facet_f", "28.62", |
| "range_facet_f1", "28.62", |
| "trait_s", "Pig", |
| "text", "line up and fly directly at the enemy death cannons, clogging them with wreckage!", |
| "zerolen_s","", |
| "foo_s","A", "foo_s","B", "foo_s","C" |
| ); |
| add_doc("id", "101", "myfield_s", "foo"); |
| add_doc("id", "102", "myfield_s", "bar"); |
| } |
| |
| static void indexSimpleGroupedFacetCounts() { |
| add_doc("id", "2000", "hotel_s1", "a", "airport_s1", "ams", "duration_i1", "5"); |
| add_doc("id", "2001", "hotel_s1", "a", "airport_s1", "dus", "duration_i1", "10"); |
| add_doc("id", "2002", "hotel_s1", "b", "airport_s1", "ams", "duration_i1", "10"); |
| add_doc("id", "2003", "hotel_s1", "b", "airport_s1", "ams", "duration_i1", "5"); |
| add_doc("id", "2004", "hotel_s1", "b", "airport_s1", "ams", "duration_i1", "5"); |
| } |
| |
| public void testDvMethodNegativeFloatRangeFacet() throws Exception { |
| String field = "negative_num_f1_dv"; |
| assertTrue("Unexpected schema configuration", h.getCore().getLatestSchema().getField(field).hasDocValues()); |
| assertEquals("Unexpected schema configuration", NumberType.FLOAT, h.getCore().getLatestSchema().getField(field).getType().getNumberType()); |
| assertFalse("Unexpected schema configuration", h.getCore().getLatestSchema().getField(field).multiValued()); |
| |
| final String[] commonParams = { |
| "q", "*:*", "facet", "true", "facet.range.start", "-2", "facet.range.end", "0", "facet.range.gap", "2" |
| }; |
| final String countAssertion |
| = "//lst[@name='facet_counts']/lst[@name='facet_ranges']/lst[@name='%s']/lst[@name='counts']/int[@name='-2.0'][.='1']"; |
| |
| assertU(adoc("id", "10001", field, "-1.0")); |
| assertU(commit()); |
| |
| assertQ(req(commonParams, "facet.range", field, "facet.range.method", "filter"), |
| String.format(Locale.ROOT, countAssertion, field) |
| ); |
| assertQ(req(commonParams, "facet.range", field, "facet.range.method", "dv"), |
| String.format(Locale.ROOT, countAssertion, field) |
| ); |
| } |
| |
| |
| public void testDefaultsAndAppends() throws Exception { |
| // all defaults |
| assertQ( req("indent","true", "q","*:*", "rows","0", "facet","true", "qt","/search-facet-def") |
| // only one default facet.field |
| ,"//lst[@name='facet_fields']/lst[@name='foo_s']" |
| ,"count(//lst[@name='facet_fields']/lst[@name='foo_s'])=1" |
| ,"count(//lst[@name='facet_fields']/lst)=1" |
| // only one default facet.query |
| ,"//lst[@name='facet_queries']/int[@name='foo_s:bar']" |
| ,"count(//lst[@name='facet_queries']/int[@name='foo_s:bar'])=1" |
| ,"count(//lst[@name='facet_queries']/int)=1" |
| ); |
| |
| // override default & pre-pend to appends |
| assertQ( req("indent","true", "q","*:*", "rows","0", "facet","true", "qt","/search-facet-def", |
| "facet.field", "bar_s", |
| "facet.query", "bar_s:yak" |
| ) |
| // override single default facet.field |
| ,"//lst[@name='facet_fields']/lst[@name='bar_s']" |
| ,"count(//lst[@name='facet_fields']/lst[@name='bar_s'])=1" |
| ,"count(//lst[@name='facet_fields']/lst)=1" |
| // add an additional facet.query |
| ,"//lst[@name='facet_queries']/int[@name='foo_s:bar']" |
| ,"//lst[@name='facet_queries']/int[@name='bar_s:yak']" |
| ,"count(//lst[@name='facet_queries']/int[@name='foo_s:bar'])=1" |
| ,"count(//lst[@name='facet_queries']/int[@name='bar_s:yak'])=1" |
| ,"count(//lst[@name='facet_queries']/int)=2" |
| ); |
| } |
| |
| public void testInvariants() throws Exception { |
| // no matter if we try to use facet.field or facet.query, results shouldn't change |
| for (String ff : new String[] { "facet.field", "bogus" }) { |
| for (String fq : new String[] { "facet.query", "bogus" }) { |
| assertQ( req("indent","true", "q", "*:*", "rows","0", "facet","true", |
| "qt","/search-facet-invariants", |
| ff, "bar_s", |
| fq, "bar_s:yak") |
| // only one invariant facet.field |
| ,"//lst[@name='facet_fields']/lst[@name='foo_s']" |
| ,"count(//lst[@name='facet_fields']/lst[@name='foo_s'])=1" |
| ,"count(//lst[@name='facet_fields']/lst)=1" |
| // only one invariant facet.query |
| ,"//lst[@name='facet_queries']/int[@name='foo_s:bar']" |
| ,"count(//lst[@name='facet_queries']/int[@name='foo_s:bar'])=1" |
| ,"count(//lst[@name='facet_queries']/int)=1" |
| ); |
| } |
| } |
| } |
| |
| @Test |
| public void testCachingBigTerms() throws Exception { |
| assertQ( req("indent","true", "q", "id_i1:[42 TO 47]", |
| "facet", "true", |
| "facet.field", "foo_s" // big terms should cause foo_s:A to be cached |
| ), |
| "*[count(//doc)=6]" |
| ); |
| |
| // now use the cached term as a filter to make sure deleted docs are accounted for |
| assertQ( req("indent","true", "fl","id", "q", "foo_s:B", |
| "facet", "true", |
| "facet.field", "foo_s", |
| "fq","foo_s:A" |
| ), |
| "*[count(//doc)=6]" |
| ); |
| |
| |
| } |
| |
| |
| @Test |
| public void testSimpleGroupedQueryRangeFacets() throws Exception { |
| // for the purposes of our test data, it shouldn't matter |
| // if we use facet.limit -100, -1, or 100 ... |
| // our set of values is small enough either way |
| testSimpleGroupedQueryRangeFacets("-100"); |
| testSimpleGroupedQueryRangeFacets("-1"); |
| testSimpleGroupedQueryRangeFacets("100"); |
| } |
| |
| private void testSimpleGroupedQueryRangeFacets(String facetLimit) { |
| assertQ( |
| req( |
| "q", "*:*", |
| "fq", "id_i1:[2000 TO 2004]", |
| "group", "true", |
| "group.facet", "true", |
| "group.field", "hotel_s1", |
| "facet", "true", |
| "facet.limit", facetLimit, |
| "facet.query", "airport_s1:ams" |
| ), |
| "//lst[@name='facet_queries']/int[@name='airport_s1:ams'][.='2']" |
| ); |
| /* Testing facet.query using tagged filter query and exclusion */ |
| assertQ( |
| req( |
| "q", "*:*", |
| "fq", "id_i1:[2000 TO 2004]", |
| "fq", "{!tag=dus}airport_s1:dus", |
| "group", "true", |
| "group.facet", "true", |
| "group.field", "hotel_s1", |
| "facet", "true", |
| "facet.limit", facetLimit, |
| "facet.query", "{!ex=dus}airport_s1:ams" |
| ), |
| "//lst[@name='facet_queries']/int[@name='{!ex=dus}airport_s1:ams'][.='2']" |
| ); |
| assertQ( |
| req( |
| "q", "*:*", |
| "fq", "id_i1:[2000 TO 2004]", |
| "group", "true", |
| "group.facet", "true", |
| "group.field", "hotel_s1", |
| "facet", "true", |
| "facet.limit", facetLimit, |
| "facet.range", "duration_i1", |
| "facet.range.start", "5", |
| "facet.range.end", "11", |
| "facet.range.gap", "1" |
| ), |
| "//lst[@name='facet_ranges']/lst[@name='duration_i1']/lst[@name='counts']/int[@name='5'][.='2']", |
| "//lst[@name='facet_ranges']/lst[@name='duration_i1']/lst[@name='counts']/int[@name='6'][.='0']", |
| "//lst[@name='facet_ranges']/lst[@name='duration_i1']/lst[@name='counts']/int[@name='7'][.='0']", |
| "//lst[@name='facet_ranges']/lst[@name='duration_i1']/lst[@name='counts']/int[@name='8'][.='0']", |
| "//lst[@name='facet_ranges']/lst[@name='duration_i1']/lst[@name='counts']/int[@name='9'][.='0']", |
| "//lst[@name='facet_ranges']/lst[@name='duration_i1']/lst[@name='counts']/int[@name='10'][.='2']" |
| ); |
| /* Testing facet.range using tagged filter query and exclusion */ |
| assertQ( |
| req( |
| "q", "*:*", |
| "fq", "id_i1:[2000 TO 2004]", |
| "fq", "{!tag=dus}airport_s1:dus", |
| "group", "true", |
| "group.facet", "true", |
| "group.field", "hotel_s1", |
| "facet", "true", |
| "facet.limit", facetLimit, |
| "facet.range", "{!ex=dus}duration_i1", |
| "facet.range.start", "5", |
| "facet.range.end", "11", |
| "facet.range.gap", "1" |
| ), |
| "//lst[@name='facet_ranges']/lst[@name='duration_i1']/lst[@name='counts']/int[@name='5'][.='2']", |
| "//lst[@name='facet_ranges']/lst[@name='duration_i1']/lst[@name='counts']/int[@name='6'][.='0']", |
| "//lst[@name='facet_ranges']/lst[@name='duration_i1']/lst[@name='counts']/int[@name='7'][.='0']", |
| "//lst[@name='facet_ranges']/lst[@name='duration_i1']/lst[@name='counts']/int[@name='8'][.='0']", |
| "//lst[@name='facet_ranges']/lst[@name='duration_i1']/lst[@name='counts']/int[@name='9'][.='0']", |
| "//lst[@name='facet_ranges']/lst[@name='duration_i1']/lst[@name='counts']/int[@name='10'][.='2']" |
| ); |
| |
| // repeat the same query using DV method. This is not supported and the query should use filter method instead |
| assertQ( |
| req( |
| "q", "*:*", |
| "fq", "id_i1:[2000 TO 2004]", |
| "fq", "{!tag=dus}airport_s1:dus", |
| "group", "true", |
| "group.facet", "true", |
| "group.field", "hotel_s1", |
| "facet", "true", |
| "facet.limit", facetLimit, |
| "facet.range", "{!ex=dus}duration_i1", |
| "facet.range.start", "5", |
| "facet.range.end", "11", |
| "facet.range.gap", "1", |
| "facet.range.method", FacetRangeMethod.DV.toString() |
| ), |
| "//lst[@name='facet_ranges']/lst[@name='duration_i1']/lst[@name='counts']/int[@name='5'][.='2']", |
| "//lst[@name='facet_ranges']/lst[@name='duration_i1']/lst[@name='counts']/int[@name='6'][.='0']", |
| "//lst[@name='facet_ranges']/lst[@name='duration_i1']/lst[@name='counts']/int[@name='7'][.='0']", |
| "//lst[@name='facet_ranges']/lst[@name='duration_i1']/lst[@name='counts']/int[@name='8'][.='0']", |
| "//lst[@name='facet_ranges']/lst[@name='duration_i1']/lst[@name='counts']/int[@name='9'][.='0']", |
| "//lst[@name='facet_ranges']/lst[@name='duration_i1']/lst[@name='counts']/int[@name='10'][.='2']" |
| ); |
| } |
| |
| @Test |
| public void testSimpleGroupedFacets() throws Exception { |
| assumeFalse("SOLR-10844: group.facet doesn't play nice with points *OR* DocValues", |
| Boolean.getBoolean(NUMERIC_DOCVALUES_SYSPROP) || Boolean.getBoolean(NUMERIC_POINTS_SYSPROP)); |
| |
| |
| // for the purposes of our test data, it shouldn't matter |
| // if we use facet.limit -100, -1, or 100 ... |
| // our set of values is small enough either way |
| testSimpleGroupedFacets("100"); |
| testSimpleGroupedFacets("-100"); |
| testSimpleGroupedFacets("-5"); |
| testSimpleGroupedFacets("-1"); |
| } |
| |
| private void testSimpleGroupedFacets(String facetLimit) throws Exception { |
| assertQ( |
| "Return 5 docs with id range 1937 till 1940", |
| req("id_i1:[2000 TO 2004]"), |
| "*[count(//doc)=5]" |
| ); |
| assertQ( |
| "Return two facet counts for field airport_a and duration_i1", |
| req( |
| "q", "*:*", |
| "fq", "id_i1:[2000 TO 2004]", |
| "group", "true", |
| "group.facet", "true", |
| "group.field", "hotel_s1", |
| "facet", "true", |
| "facet.limit", facetLimit, |
| "facet.field", "airport_s1", |
| "facet.field", "duration_i1" |
| ), |
| "//lst[@name='facet_fields']/lst[@name='airport_s1']", |
| "*[count(//lst[@name='airport_s1']/int)=2]", |
| "//lst[@name='airport_s1']/int[@name='ams'][.='2']", |
| "//lst[@name='airport_s1']/int[@name='dus'][.='1']", |
| |
| "//lst[@name='facet_fields']/lst[@name='duration_i1']", |
| "*[count(//lst[@name='duration_i1']/int)=2]", |
| "//lst[@name='duration_i1']/int[@name='5'][.='2']", |
| "//lst[@name='duration_i1']/int[@name='10'][.='2']" |
| ); |
| assertQ( |
| "Return one facet count for field airport_a using facet.offset", |
| req( |
| "q", "*:*", |
| "fq", "id_i1:[2000 TO 2004]", |
| "group", "true", |
| "group.facet", "true", |
| "group.field", "hotel_s1", |
| "facet", "true", |
| "facet.offset", "1", |
| "facet.limit", facetLimit, |
| "facet.field", "airport_s1" |
| ), |
| "//lst[@name='facet_fields']/lst[@name='airport_s1']", |
| "*[count(//lst[@name='airport_s1']/int)=1]", |
| "//lst[@name='airport_s1']/int[@name='dus'][.='1']" |
| ); |
| assertQ( |
| "Return two facet counts for field airport_a with fq", |
| req( |
| "q", "*:*", |
| "fq", "id_i1:[2000 TO 2004]", |
| "fq", "duration_i1:5", |
| "group", "true", |
| "group.facet", "true", |
| "group.field", "hotel_s1", |
| "facet", "true", |
| "facet.limit", facetLimit, |
| "facet.field", "airport_s1" |
| ), |
| "//lst[@name='facet_fields']/lst[@name='airport_s1']", |
| "*[count(//lst[@name='airport_s1']/int)=2]", |
| "//lst[@name='airport_s1']/int[@name='ams'][.='2']", |
| "//lst[@name='airport_s1']/int[@name='dus'][.='0']" |
| ); |
| assertQ( |
| "Return one facet count for field airport_s1 with prefix a", |
| req( |
| "q", "*:*", |
| "fq", "id_i1:[2000 TO 2004]", |
| "group", "true", |
| "group.facet", "true", |
| "group.field", "hotel_s1", |
| "facet", "true", |
| "facet.field", "airport_s1", |
| "facet.limit", facetLimit, |
| "facet.prefix", "a" |
| ), |
| "//lst[@name='facet_fields']/lst[@name='airport_s1']", |
| "*[count(//lst[@name='airport_s1']/int)=1]", |
| "//lst[@name='airport_s1']/int[@name='ams'][.='2']" |
| ); |
| |
| SolrException e = expectThrows(SolrException.class, () -> { |
| h.query( |
| req( |
| "q", "*:*", |
| "fq", "id_i1:[2000 TO 2004]", |
| "group.facet", "true", |
| "facet", "true", |
| "facet.field", "airport_s1", |
| "facet.prefix", "a" |
| ) |
| ); |
| }); |
| assertEquals(SolrException.ErrorCode.BAD_REQUEST.code, e.code()); |
| } |
| |
| @Test |
| public void testEmptyFacetCounts() throws Exception { |
| doEmptyFacetCounts(); |
| } |
| |
| // static so we can try both with and without an empty index |
| static void doEmptyFacetCounts() throws Exception { |
| doEmptyFacetCounts("empty_t", new String[]{null, "myprefix",""}); |
| doEmptyFacetCounts("empty_i", new String[]{null}); |
| doEmptyFacetCounts("empty_f", new String[]{null}); |
| doEmptyFacetCounts("empty_s", new String[]{null, "myprefix",""}); |
| doEmptyFacetCounts("empty_d", new String[]{null}); |
| } |
| |
| static void doEmptyFacetCounts(String field, String[] prefixes) throws Exception { |
| SchemaField sf = h.getCore().getLatestSchema().getField(field); |
| |
| String response = JQ(req("q", "*:*")); |
| @SuppressWarnings({"rawtypes"}) |
| Map rsp = (Map) fromJSONString(response); |
| Long numFound = (Long)(((Map)rsp.get("response")).get("numFound")); |
| |
| ModifiableSolrParams params = params("q","*:*", "facet.mincount","1","rows","0", "facet","true", "facet.field","{!key=myalias}"+field); |
| |
| String[] methods = {null, "fc","enum","fcs", "uif"}; |
| if (sf.multiValued() || sf.getType().multiValuedFieldCache()) { |
| methods = new String[]{null, "fc","enum", "uif"}; |
| } |
| |
| prefixes = prefixes==null ? new String[]{null} : prefixes; |
| |
| |
| for (String method : methods) { |
| if (method == null) { |
| params.remove("facet.method"); |
| } else { |
| params.set("facet.method", method); |
| } |
| for (String prefix : prefixes) { |
| if (prefix == null) { |
| params.remove("facet.prefix"); |
| } else { |
| params.set("facet.prefix", prefix); |
| } |
| |
| for (String missing : new String[] {null, "true"}) { |
| if (missing == null) { |
| params.remove("facet.missing"); |
| } else { |
| params.set("facet.missing", missing); |
| } |
| |
| String expected = missing==null ? "[]" : "[null," + numFound + "]"; |
| |
| assertJQ(req(params), |
| "/facet_counts/facet_fields/myalias==" + expected); |
| } |
| } |
| } |
| } |
| |
| |
| @Test |
| public void testFacetMatches() { |
| final String[][] uifSwitch = new String[][] { |
| new String[]{"f.trait_s.facet.method", "uif"}, |
| new String[]{"facet.method", "uif"} |
| }; |
| final String[] none = new String[]{}; |
| for (String[] aSwitch : uifSwitch) { |
| for(String[] methodParam : new String[][]{ none, aSwitch}) { |
| assertQ("check facet.match filters facets returned", |
| req(methodParam |
| , "q", "id:[42 TO 47]" |
| , "facet", "true" |
| , "facet.field", "trait_s" |
| , "facet.matches", ".*o.*" |
| ) |
| , "*[count(//doc)=6]" |
| |
| , "//lst[@name='facet_counts']/lst[@name='facet_queries']" |
| |
| , "//lst[@name='facet_counts']/lst[@name='facet_fields']" |
| , "//lst[@name='facet_fields']/lst[@name='trait_s']" |
| , "*[count(//lst[@name='trait_s']/int)=2]" |
| , "//lst[@name='trait_s']/int[@name='Tool'][.='2']" |
| , "//lst[@name='trait_s']/int[@name='Obnoxious'][.='2']" |
| ); |
| } |
| } |
| } |
| |
| @Test |
| public void testFacetMissing() { |
| SolrParams commonParams = params("q", "foo_s:A", "rows", "0", "facet", "true", "facet.missing", "true"); |
| |
| // with facet.limit!=0 and facet.missing=true |
| assertQ( |
| req(commonParams, "facet.field", "trait_s", "facet.limit", "1"), |
| "//lst[@name='facet_counts']/lst[@name='facet_fields']", |
| "//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='trait_s']", |
| "*[count(//lst[@name='trait_s']/int)=2]", |
| "//lst[@name='trait_s']/int[@name='Obnoxious'][.='2']", |
| "//lst[@name='trait_s']/int[.='1']" |
| ); |
| |
| // with facet.limit=0 and facet.missing=true |
| assertQ( |
| req(commonParams, "facet.field", "trait_s", "facet.limit", "0"), |
| "//lst[@name='facet_counts']/lst[@name='facet_fields']", |
| "//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='trait_s']", |
| "*[count(//lst[@name='trait_s']/int)=1]", |
| "//lst[@name='trait_s']/int[.='1']" |
| ); |
| |
| // facet.method=enum |
| assertQ( |
| req(commonParams, "facet.field", "trait_s", "facet.limit", "0", "facet.method", "enum"), |
| "//lst[@name='facet_counts']/lst[@name='facet_fields']", |
| "//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='trait_s']", |
| "*[count(//lst[@name='trait_s']/int)=1]", |
| "//lst[@name='trait_s']/int[.='1']" |
| ); |
| |
| assertQ( |
| req(commonParams, "facet.field", "trait_s", "facet.limit", "0", "facet.mincount", "1", |
| "facet.method", "uif"), |
| "//lst[@name='facet_counts']/lst[@name='facet_fields']", |
| "//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='trait_s']", |
| "*[count(//lst[@name='trait_s']/int)=1]", |
| "//lst[@name='trait_s']/int[.='1']" |
| ); |
| |
| // facet.method=fcs |
| assertQ( |
| req(commonParams, "facet.field", "trait_s", "facet.limit", "0", "facet.method", "fcs"), |
| "//lst[@name='facet_counts']/lst[@name='facet_fields']", |
| "//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='trait_s']", |
| "*[count(//lst[@name='trait_s']/int)=1]", |
| "//lst[@name='trait_s']/int[.='1']" |
| ); |
| |
| // facet.missing=true on numeric field |
| assertQ( |
| req(commonParams, "facet.field", "range_facet_f", "facet.limit", "1", "facet.mincount", "1"), |
| "//lst[@name='facet_counts']/lst[@name='facet_fields']", |
| "//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='range_facet_f']", |
| "*[count(//lst[@name='range_facet_f']/int)=2]", |
| "//lst[@name='range_facet_f']/int[.='0']" |
| ); |
| |
| // facet.limit=0 |
| assertQ( |
| req(commonParams, "facet.field", "range_facet_f", "facet.limit", "0", "facet.mincount", "1"), |
| "//lst[@name='facet_counts']/lst[@name='facet_fields']", |
| "//lst[@name='facet_counts']/lst[@name='facet_fields']/lst[@name='range_facet_f']", |
| "*[count(//lst[@name='range_facet_f']/int)=1]", |
| "//lst[@name='range_facet_f']/int[.='0']" |
| ); |
| } |
| |
| @Test |
| public void testSimpleFacetCounts() { |
| |
| assertQ("standard request handler returns all matches", |
| req("id_i1:[42 TO 47]"), |
| "*[count(//doc)=6]" |
| ); |
| |
| assertQ("filter results using fq", |
| req("q","id_i1:[42 TO 46]", |
| "fq", "id_i1:[43 TO 47]"), |
| "*[count(//doc)=4]" |
| ); |
| |
| assertQ("don't filter results using blank fq", |
| req("q","id_i1:[42 TO 46]", |
| "fq", " "), |
| "*[count(//doc)=5]" |
| ); |
| |
| assertQ("filter results using multiple fq params", |
| req("q","id_i1:[42 TO 46]", |
| "fq", "trait_s:Obnoxious", |
| "fq", "id_i1:[43 TO 47]"), |
| "*[count(//doc)=1]" |
| ); |
| |
| final String[] uifSwitch = new String[]{(random().nextBoolean() ? "":"f.trait_s.")+"facet.method", "uif"}; |
| final String[] none = new String[]{}; |
| |
| for(String[] methodParam : new String[][]{ none, uifSwitch}){ |
| assertQ("check counts for facet queries", |
| req(methodParam |
| ,"q", "id_i1:[42 TO 47]" |
| ,"facet", "true" |
| ,"facet.query", "trait_s:Obnoxious" |
| ,"facet.query", "id_i1:[42 TO 45]" |
| ,"facet.query", "id_i1:[43 TO 47]" |
| ,"facet.field", "trait_s" |
| ) |
| ,"*[count(//doc)=6]" |
| |
| ,"//lst[@name='facet_counts']/lst[@name='facet_queries']" |
| ,"//lst[@name='facet_queries']/int[@name='trait_s:Obnoxious'][.='2']" |
| ,"//lst[@name='facet_queries']/int[@name='id_i1:[42 TO 45]'][.='4']" |
| ,"//lst[@name='facet_queries']/int[@name='id_i1:[43 TO 47]'][.='5']" |
| |
| ,"//lst[@name='facet_counts']/lst[@name='facet_fields']" |
| ,"//lst[@name='facet_fields']/lst[@name='trait_s']" |
| ,"*[count(//lst[@name='trait_s']/int)=4]" |
| ,"//lst[@name='trait_s']/int[@name='Tool'][.='2']" |
| ,"//lst[@name='trait_s']/int[@name='Obnoxious'][.='2']" |
| ,"//lst[@name='trait_s']/int[@name='Pig'][.='1']" |
| ); |
| |
| assertQ("check multi-select facets with naming", |
| req(methodParam, "q", "id_i1:[42 TO 47]" |
| ,"facet", "true" |
| ,"facet.query", "{!ex=1}trait_s:Obnoxious" |
| ,"facet.query", "{!ex=2 key=foo}id_i1:[42 TO 45]" // tag=2 same as 1 |
| ,"facet.query", "{!ex=3,4 key=bar}id_i1:[43 TO 47]" // tag=3,4 don't exist |
| ,"facet.field", "{!ex=3,1}trait_s" // 3,1 same as 1 |
| ,"fq", "{!tag=1,2}id:47" // tagged as 1 and 2 |
| ) |
| ,"*[count(//doc)=1]" |
| |
| ,"//lst[@name='facet_counts']/lst[@name='facet_queries']" |
| ,"//lst[@name='facet_queries']/int[@name='{!ex=1}trait_s:Obnoxious'][.='2']" |
| ,"//lst[@name='facet_queries']/int[@name='foo'][.='4']" |
| ,"//lst[@name='facet_queries']/int[@name='bar'][.='1']" |
| |
| ,"//lst[@name='facet_counts']/lst[@name='facet_fields']" |
| ,"//lst[@name='facet_fields']/lst[@name='trait_s']" |
| ,"*[count(//lst[@name='trait_s']/int)=4]" |
| ,"//lst[@name='trait_s']/int[@name='Tool'][.='2']" |
| ,"//lst[@name='trait_s']/int[@name='Obnoxious'][.='2']" |
| ,"//lst[@name='trait_s']/int[@name='Pig'][.='1']" |
| ); |
| } |
| // test excluding main query |
| assertQ(req("q", "{!tag=main}id:43" |
| ,"facet", "true" |
| ,"facet.query", "{!key=foo}id:42" |
| ,"facet.query", "{!ex=main key=bar}id:42" // only matches when we exclude main query |
| ) |
| ,"//lst[@name='facet_queries']/int[@name='foo'][.='0']" |
| ,"//lst[@name='facet_queries']/int[@name='bar'][.='1']" |
| ); |
| |
| for(String[] methodParam : new String[][]{ none, uifSwitch}){ |
| assertQ("check counts for applied facet queries using filtering (fq)", |
| req(methodParam |
| ,"q", "id_i1:[42 TO 47]" |
| ,"facet", "true" |
| ,"fq", "id_i1:[42 TO 45]" |
| ,"facet.field", "trait_s" |
| ,"facet.query", "id_i1:[42 TO 45]" |
| ,"facet.query", "id_i1:[43 TO 47]" |
| ) |
| ,"*[count(//doc)=4]" |
| ,"//lst[@name='facet_counts']/lst[@name='facet_queries']" |
| ,"//lst[@name='facet_queries']/int[@name='id_i1:[42 TO 45]'][.='4']" |
| ,"//lst[@name='facet_queries']/int[@name='id_i1:[43 TO 47]'][.='3']" |
| ,"*[count(//lst[@name='trait_s']/int)=4]" |
| ,"//lst[@name='trait_s']/int[@name='Tool'][.='2']" |
| ,"//lst[@name='trait_s']/int[@name='Obnoxious'][.='1']" |
| ,"//lst[@name='trait_s']/int[@name='Chauvinist'][.='1']" |
| ,"//lst[@name='trait_s']/int[@name='Pig'][.='0']" |
| ); |
| |
| assertQ("check counts with facet.zero=false&facet.missing=true using fq", |
| req(methodParam |
| ,"q", "id_i1:[42 TO 47]" |
| ,"facet", "true" |
| ,"facet.zeros", "false" |
| ,"f.trait_s.facet.missing", "true" |
| ,"fq", "id_i1:[42 TO 45]" |
| ,"facet.field", "trait_s" |
| ) |
| ,"*[count(//doc)=4]" |
| ,"*[count(//lst[@name='trait_s']/int)=4]" |
| ,"//lst[@name='trait_s']/int[@name='Tool'][.='2']" |
| ,"//lst[@name='trait_s']/int[@name='Obnoxious'][.='1']" |
| ,"//lst[@name='trait_s']/int[@name='Chauvinist'][.='1']" |
| ,"//lst[@name='trait_s']/int[not(@name)][.='1']" |
| ); |
| |
| assertQ("check counts with facet.mincount=1&facet.missing=true using fq", |
| req(methodParam |
| ,"q", "id_i1:[42 TO 47]" |
| ,"facet", "true" |
| ,"facet.mincount", "1" |
| ,"f.trait_s.facet.missing", "true" |
| ,"fq", "id_i1:[42 TO 45]" |
| ,"facet.field", "trait_s" |
| ) |
| ,"*[count(//doc)=4]" |
| ,"*[count(//lst[@name='trait_s']/int)=4]" |
| ,"//lst[@name='trait_s']/int[@name='Tool'][.='2']" |
| ,"//lst[@name='trait_s']/int[@name='Obnoxious'][.='1']" |
| ,"//lst[@name='trait_s']/int[@name='Chauvinist'][.='1']" |
| ,"//lst[@name='trait_s']/int[not(@name)][.='1']" |
| ); |
| |
| assertQ("check counts with facet.mincount=2&facet.missing=true using fq", |
| req(methodParam |
| ,"q", "id_i1:[42 TO 47]" |
| ,"facet", "true" |
| ,"facet.mincount", "2" |
| ,"f.trait_s.facet.missing", "true" |
| ,"fq", "id_i1:[42 TO 45]" |
| ,"facet.field", "trait_s" |
| ) |
| ,"*[count(//doc)=4]" |
| ,"*[count(//lst[@name='trait_s']/int)=2]" |
| ,"//lst[@name='trait_s']/int[@name='Tool'][.='2']" |
| ,"//lst[@name='trait_s']/int[not(@name)][.='1']" |
| ); |
| |
| assertQ("check sorted paging", |
| req(methodParam |
| ,"q", "id_i1:[42 TO 47]" |
| ,"facet", "true" |
| ,"fq", "id_i1:[42 TO 45]" |
| ,"facet.field", "trait_s" |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","4" |
| ) |
| ,"*[count(//lst[@name='trait_s']/int)=4]" |
| ,"//lst[@name='trait_s']/int[@name='Tool'][.='2']" |
| ,"//lst[@name='trait_s']/int[@name='Obnoxious'][.='1']" |
| ,"//lst[@name='trait_s']/int[@name='Chauvinist'][.='1']" |
| ,"//lst[@name='trait_s']/int[@name='Pig'][.='0']" |
| ); |
| |
| // check that the default sort is by count |
| assertQ("check sorted paging", |
| req(methodParam, "q", "id_i1:[42 TO 47]" |
| ,"facet", "true" |
| ,"fq", "id_i1:[42 TO 45]" |
| ,"facet.field", "trait_s" |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","3" |
| ) |
| ,"*[count(//lst[@name='trait_s']/int)=3]" |
| ,"//int[1][@name='Tool'][.='2']" |
| ,"//int[2][@name='Chauvinist'][.='1']" |
| ,"//int[3][@name='Obnoxious'][.='1']" |
| ); |
| |
| // |
| // check that legacy facet.sort=true/false works |
| // |
| assertQ(req(methodParam, "q", "id_i1:[42 TO 47]" |
| ,"facet", "true" |
| ,"fq", "id_i1:[42 TO 45]" |
| ,"facet.field", "trait_s" |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","3" |
| ,"facet.sort","true" // true means sort-by-count |
| ) |
| ,"*[count(//lst[@name='trait_s']/int)=3]" |
| ,"//int[1][@name='Tool'][.='2']" |
| ,"//int[2][@name='Chauvinist'][.='1']" |
| ,"//int[3][@name='Obnoxious'][.='1']" |
| ); |
| |
| assertQ(req(methodParam, "q", "id_i1:[42 TO 47]" |
| ,"facet", "true" |
| ,"fq", "id_i1:[42 TO 45]" |
| ,"facet.field", "trait_s" |
| ,"facet.mincount","1" |
| ,"facet.offset","0" |
| ,"facet.limit","3" |
| ,"facet.sort","false" // false means sort by index order |
| ) |
| ,"*[count(//lst[@name='trait_s']/int)=3]" |
| ,"//int[1][@name='Chauvinist'][.='1']" |
| ,"//int[2][@name='Obnoxious'][.='1']" |
| ,"//int[3][@name='Tool'][.='2']" |
| ); |
| } |
| |
| for(String method : new String[]{ "fc","uif"}){ |
| assertQ(req("q", "id_i1:[42 TO 47]" |
| ,"facet", "true" |
| ,"fq", "id_i1:[42 TO 45]" |
| ,"facet.field", "zerolen_s" |
| ,(random().nextBoolean() ? "":"f.zerolen_s.")+"facet.method", method |
| ) |
| ,"*[count(//lst[@name='zerolen_s']/int[@name=''])=1]" |
| ); |
| } |
| |
| assertQ("a facet.query that analyzes to no query shoud not NPE", |
| req("q", "*:*", |
| "facet", "true", |
| "facet.query", "{!field key=k f=lengthfilt}a"),//2 char minimum |
| "//lst[@name='facet_queries']/int[@name='k'][.='0']" |
| ); |
| } |
| |
| public void testBehaviorEquivilenceOfUninvertibleFalse() throws Exception { |
| // NOTE: mincount=0 affects method detection/coercion, so we include permutations of it |
| |
| { |
| // an "uninvertible=false" field is not be facetable using the "default" method, |
| // or any explicit method other then "enum". |
| // |
| // it should behave the same as any attempt (using any method) at faceting on |
| // and "indexed=false docValues=false" field -- returning no buckets. |
| |
| final List<SolrParams> paramSets = new ArrayList<>(); |
| for (String min : Arrays.asList("0", "1")) { |
| for (String f : Arrays.asList("trait_s_not_uninvert", "trait_s_not_indexed_sS")) { |
| paramSets.add(params("facet.field", "{!key=x}" + f)); |
| for (String method : Arrays.asList("fc", "fcs", "uif")) { |
| paramSets.add(params("facet.field", "{!key=x}" + f, |
| "facet.mincount", min, |
| "facet.method", method)); |
| paramSets.add(params("facet.field", "{!key=x}" + f, |
| "facet.mincount", min, |
| "facet.method", method)); |
| } |
| } |
| paramSets.add(params("facet.field", "{!key=x}trait_s_not_indexed_sS", |
| "facet.mincount", min, |
| "facet.method", "enum")); |
| } |
| for (SolrParams p : paramSets) { |
| // "empty" results should be the same regardless of mincount |
| assertQ("expect no buckets when field is not-indexed or not-uninvertible", |
| req(p |
| ,"rows","0" |
| ,"q", "id_i1:[42 TO 47]" |
| ,"fq", "id_i1:[42 TO 45]" |
| ,"facet", "true" |
| ) |
| ,"//*[@numFound='4']" |
| ,"*[count(//lst[@name='x'])=1]" |
| ,"*[count(//lst[@name='x']/int)=0]" |
| ); |
| } |
| |
| } |
| |
| { |
| // the only way to facet on an "uninvertible=false" field is to explicitly request facet.method=enum |
| // in which case it should behave consistently with it's copyField source & equivilent docValues field |
| // (using any method for either of them) |
| |
| final List<SolrParams> paramSets = new ArrayList<>(); |
| for (String min : Arrays.asList("0", "1")) { |
| paramSets.add(params("facet.field", "{!key=x}trait_s_not_uninvert", |
| "facet.method", "enum")); |
| for (String okField : Arrays.asList("trait_s", "trait_s_not_uninvert_dv")) { |
| paramSets.add(params("facet.field", "{!key=x}" + okField)); |
| for (String method : Arrays.asList("enum","fc", "fcs", "uif")) { |
| paramSets.add(params("facet.field", "{!key=x}" + okField, |
| "facet.method", method)); |
| } |
| } |
| for (SolrParams p : paramSets) { |
| assertQ("check counts for applied facet queries using filtering (fq)", |
| req(p |
| ,"rows","0" |
| ,"q", "id_i1:[42 TO 47]" |
| ,"fq", "id_i1:[42 TO 45]" |
| ,"facet", "true" |
| ,"facet.mincount", min |
| ) |
| ,"//*[@numFound='4']" |
| ,"*[count(//lst[@name='x'])=1]" |
| ,"*[count(//lst[@name='x']/int)="+("0".equals(min) ? "4]" : "3]") |
| ,"//lst[@name='x']/int[@name='Tool'][.='2']" |
| ,"//lst[@name='x']/int[@name='Obnoxious'][.='1']" |
| ,"//lst[@name='x']/int[@name='Chauvinist'][.='1']" |
| ,"count(//lst[@name='x']/int[@name='Pig'][.='0'])=" + ("0".equals(min) ? "1" : "0") |
| ); |
| } |
| } |
| } |
| } |
| |
| |
| public static void indexDateFacets() { |
| final String i = "id"; |
| final String f = "bday"; |
| final String ff = "a_tdt"; |
| final String ooo = "00:00:00.000Z"; |
| final String xxx = "15:15:15.155Z"; |
| |
| //note: add_doc duplicates bday to bday_drf and a_tdt to a_drf (date range field) |
| add_doc(i, "201", f, "1976-07-04T12:08:56.235Z", ff, "1900-01-01T"+ooo); |
| add_doc(i, "202", f, "1976-07-05T00:00:00.000Z", ff, "1976-07-01T"+ooo); |
| add_doc(i, "203", f, "1976-07-15T00:07:57.890Z", ff, "1976-07-04T"+ooo); |
| add_doc(i, "204", f, "1976-07-21T00:07:57.890Z", ff, "1976-07-05T"+ooo); |
| add_doc(i, "205", f, "1976-07-13T12:12:25.255Z", ff, "1976-07-05T"+xxx); |
| add_doc(i, "206", f, "1976-07-03T17:01:23.456Z", ff, "1976-07-07T"+ooo); |
| add_doc(i, "207", f, "1976-07-12T12:12:25.255Z", ff, "1976-07-13T"+ooo); |
| add_doc(i, "208", f, "1976-07-15T15:15:15.155Z", ff, "1976-07-13T"+xxx); |
| add_doc(i, "209", f, "1907-07-12T13:13:23.235Z", ff, "1976-07-15T"+xxx); |
| add_doc(i, "2010", f, "1976-07-03T11:02:45.678Z", ff, "2000-01-01T"+ooo); |
| add_doc(i, "2011", f, "1907-07-12T12:12:25.255Z"); |
| add_doc(i, "2012", f, "2007-07-30T07:07:07.070Z"); |
| add_doc(i, "2013", f, "1976-07-30T22:22:22.222Z"); |
| add_doc(i, "2014", f, "1976-07-05T22:22:22.222Z"); |
| } |
| |
| @Test |
| public void testTrieDateRangeFacets() { |
| helpTestDateFacets("bday", FacetRangeMethod.FILTER); |
| } |
| |
| @Test |
| public void testTrieDateRangeFacetsDocValues() { |
| helpTestDateFacets("bday", FacetRangeMethod.DV); |
| } |
| |
| @Test |
| public void testDateRangeFieldFacets() { |
| helpTestDateFacets("bday_drf", FacetRangeMethod.FILTER); |
| } |
| |
| private void helpTestDateFacets(final String fieldName, final FacetRangeMethod rangeFacetMethod) { |
| final String p = "facet.range"; |
| final String b = "facet_ranges"; |
| final String f = fieldName; |
| final String c = "/lst[@name='counts']"; |
| final String pre = "//lst[@name='"+b+"']/lst[@name='"+f+"']" + c; |
| final String meta = pre + "/../"; |
| |
| |
| // range faceting defaults to including only lower endpoint |
| // doc exists with value @ 00:00:00.000 on July5 |
| final String jul4 = "[.='1' ]"; |
| |
| assertQ("check counts for month of facet by day", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,p, f |
| ,p+".start", "1976-07-01T00:00:00.000Z" |
| ,p+".end", "1976-07-01T00:00:00.000Z+1MONTH" |
| ,p+".gap", "+1DAY" |
| ,p+".other", "all" |
| ,p+".method", rangeFacetMethod.toString() //This only applies to range faceting, won't be use for date faceting |
| ) |
| ,"*[count("+pre+"/int)=31]" |
| ,pre+"/int[@name='1976-07-01T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-02T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-03T00:00:00Z'][.='2' ]" |
| ,pre+"/int[@name='1976-07-04T00:00:00Z']" + jul4 |
| ,pre+"/int[@name='1976-07-05T00:00:00Z'][.='2' ]" |
| ,pre+"/int[@name='1976-07-06T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-07T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-08T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-09T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-10T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-11T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-12T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-13T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-14T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-15T00:00:00Z'][.='2' ]" |
| ,pre+"/int[@name='1976-07-16T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-17T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-18T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-19T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-21T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-22T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-23T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-24T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-25T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-26T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-27T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-28T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-29T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-30T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-31T00:00:00Z'][.='0']" |
| |
| ,meta+"/int[@name='before' ][.='2']" |
| ,meta+"/int[@name='after' ][.='1']" |
| ,meta+"/int[@name='between'][.='11']" |
| |
| ); |
| |
| assertQ("check counts for month of facet by day with global mincount = 1", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,p, f |
| ,p+".start", "1976-07-01T00:00:00.000Z" |
| ,p+".end", "1976-07-01T00:00:00.000Z+1MONTH" |
| ,p+".gap", "+1DAY" |
| ,p+".other", "all" |
| ,"facet.mincount", "1" |
| ) |
| ,"*[count("+pre+"/int)=8]" |
| ,pre+"/int[@name='1976-07-03T00:00:00Z'][.='2' ]" |
| ,pre+"/int[@name='1976-07-04T00:00:00Z']" + jul4 |
| ,pre+"/int[@name='1976-07-05T00:00:00Z'][.='2' ]" |
| ,pre+"/int[@name='1976-07-12T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-13T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-15T00:00:00Z'][.='2' ]" |
| ,pre+"/int[@name='1976-07-21T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-30T00:00:00Z'][.='1' ]" |
| ,meta+"/int[@name='before' ][.='2']" |
| ,meta+"/int[@name='after' ][.='1']" |
| ,meta+"/int[@name='between'][.='11']" |
| ); |
| |
| assertQ("check counts for month of facet by day with field mincount = 1", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,p, f |
| ,p+".start", "1976-07-01T00:00:00.000Z" |
| ,p+".end", "1976-07-01T00:00:00.000Z+1MONTH" |
| ,p+".gap", "+1DAY" |
| ,p+".other", "all" |
| ,"f." + f + ".facet.mincount", "2" |
| ) |
| ,"*[count("+pre+"/int)=3]" |
| ,pre+"/int[@name='1976-07-03T00:00:00Z'][.='2' ]" |
| ,pre |
| ,pre+"/int[@name='1976-07-05T00:00:00Z'][.='2' ]" |
| ,pre+"/int[@name='1976-07-15T00:00:00Z'][.='2' ]" |
| ,meta+"/int[@name='before' ][.='2']" |
| ,meta+"/int[@name='after' ][.='1']" |
| ,meta+"/int[@name='between'][.='11']" |
| ); |
| |
| assertQ("check before is not inclusive of upper bound by default", |
| req("q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,p, f |
| ,p+".start", "1976-07-05T00:00:00.000Z" |
| ,p+".end", "1976-07-07T00:00:00.000Z" |
| ,p+".gap", "+1DAY" |
| ,p+".other", "all" |
| ) |
| ,"*[count("+pre+"/int)=2]" |
| ,pre+"/int[@name='1976-07-05T00:00:00Z'][.='2' ]" |
| ,pre+"/int[@name='1976-07-06T00:00:00Z'][.='0']" |
| |
| ,meta+"/int[@name='before' ][.='5']" |
| ); |
| assertQ("check after is not inclusive of lower bound by default (for dates)", |
| req("q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,p, f |
| ,p+".start", "1976-07-03T00:00:00.000Z" |
| ,p+".end", "1976-07-05T00:00:00.000Z" |
| ,p+".gap", "+1DAY" |
| ,p+".other", "all" |
| ) |
| ,"*[count("+pre+"/int)=2]" |
| ,pre+"/int[@name='1976-07-03T00:00:00Z'][.='2' ]" |
| ,pre+"/int[@name='1976-07-04T00:00:00Z']" + jul4 |
| |
| ,meta+"/int[@name='after' ][.='9']" |
| ); |
| |
| |
| assertQ("check hardend=false", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,p, f |
| ,p+".start", "1976-07-01T00:00:00.000Z" |
| ,p+".end", "1976-07-13T00:00:00.000Z" |
| ,p+".gap", "+5DAYS" |
| ,p+".other", "all" |
| ,p+".hardend","false" |
| ) |
| ,"*[count("+pre+"/int)=3]" |
| ,pre+"/int[@name='1976-07-01T00:00:00Z'][.='5' ]" |
| ,pre+"/int[@name='1976-07-06T00:00:00Z'][.='0' ]" |
| ,pre+"/int[@name='1976-07-11T00:00:00Z'][.='4' ]" |
| |
| ,meta+"/int[@name='before' ][.='2']" |
| ,meta+"/int[@name='after' ][.='3']" |
| ,meta+"/int[@name='between'][.='9']" |
| ); |
| |
| assertQ("check hardend=true", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,p, f |
| ,p+".start", "1976-07-01T00:00:00.000Z" |
| ,p+".end", "1976-07-13T00:00:00.000Z" |
| ,p+".gap", "+5DAYS" |
| ,p+".other", "all" |
| ,p+".hardend","true" |
| ) |
| ,"*[count("+pre+"/int)=3]" |
| ,pre+"/int[@name='1976-07-01T00:00:00Z'][.='5' ]" |
| ,pre+"/int[@name='1976-07-06T00:00:00Z'][.='0' ]" |
| ,pre+"/int[@name='1976-07-11T00:00:00Z'][.='1' ]" |
| |
| ,meta+"/int[@name='before' ][.='2']" |
| ,meta+"/int[@name='after' ][.='6']" |
| ,meta+"/int[@name='between'][.='6']" |
| ); |
| |
| //Fixed by SOLR-9080 related to the Gregorian Change Date |
| assertQ("check BC era", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,p, f |
| ,p+".start", "-0200-01-01T00:00:00Z" // BC |
| ,p+".end", "+0200-01-01T00:00:00Z" // AD |
| ,p+".gap", "+100YEARS" |
| ,p+".other", "all" |
| ) |
| ,pre+"/int[@name='-0200-01-01T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='-0100-01-01T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='0000-01-01T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='0100-01-01T00:00:00Z'][.='0']" |
| ,meta+"/int[@name='before' ][.='0']" |
| ,meta+"/int[@name='after' ][.='14']" |
| ,meta+"/int[@name='between'][.='0']" |
| |
| ); |
| |
| } |
| |
| @Test |
| public void testTrieDateRangeFacetsWithIncludeOption() { |
| helpTestDateRangeFacetsWithIncludeOption("a_tdt"); |
| } |
| |
| @Test |
| public void testDateRangeFieldDateRangeFacetsWithIncludeOption() { |
| helpTestDateRangeFacetsWithIncludeOption("a_drf"); |
| } |
| |
| /** Similar to helpTestDateFacets, but for different fields with test data |
| exactly on boundary marks */ |
| private void helpTestDateRangeFacetsWithIncludeOption(final String fieldName) { |
| final String p = "facet.range"; |
| final String b = "facet_ranges"; |
| final String f = fieldName; |
| final String c = "/lst[@name='counts']"; |
| final String pre = "//lst[@name='"+b+"']/lst[@name='"+f+"']" + c; |
| final String meta = pre + "/../"; |
| |
| assertQ("checking counts for lower", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,p, f |
| ,p+".start", "1976-07-01T00:00:00.000Z" |
| ,p+".end", "1976-07-16T00:00:00.000Z" |
| ,p+".gap", "+1DAY" |
| ,p+".other", "all" |
| ,p+".include", "lower" |
| ) |
| // 15 days + pre+post+inner = 18 |
| ,"*[count("+pre+"/int)=15]" |
| ,pre+"/int[@name='1976-07-01T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-02T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-03T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-04T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-05T00:00:00Z'][.='2' ]" |
| ,pre+"/int[@name='1976-07-06T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-07T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-08T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-09T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-10T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-11T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-12T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-13T00:00:00Z'][.='2' ]" |
| ,pre+"/int[@name='1976-07-14T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-15T00:00:00Z'][.='1' ]" |
| // |
| ,meta+"/int[@name='before' ][.='1']" |
| ,meta+"/int[@name='after' ][.='1']" |
| ,meta+"/int[@name='between'][.='8']" |
| ); |
| |
| assertQ("checking counts for upper", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,p, f |
| ,p+".start", "1976-07-01T00:00:00.000Z" |
| ,p+".end", "1976-07-16T00:00:00.000Z" |
| ,p+".gap", "+1DAY" |
| ,p+".other", "all" |
| ,p+".include", "upper" |
| ) |
| // 15 days + pre+post+inner = 18 |
| ,"*[count("+pre+"/int)=15]" |
| ,pre+"/int[@name='1976-07-01T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-02T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-03T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-04T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-05T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-06T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-07T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-08T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-09T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-10T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-11T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-12T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-13T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-14T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-15T00:00:00Z'][.='1' ]" |
| // |
| ,meta+"/int[@name='before' ][.='2']" |
| ,meta+"/int[@name='after' ][.='1']" |
| ,meta+"/int[@name='between'][.='7']" |
| ); |
| |
| assertQ("checking counts for lower & upper", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,p, f |
| ,p+".start", "1976-07-01T00:00:00.000Z" |
| ,p+".end", "1976-07-16T00:00:00.000Z" |
| ,p+".gap", "+1DAY" |
| ,p+".other", "all" |
| ,p+".include", "lower" |
| ,p+".include", "upper" |
| ) |
| // 15 days + pre+post+inner = 18 |
| ,"*[count("+pre+"/int)=15]" |
| ,pre+"/int[@name='1976-07-01T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-02T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-03T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-04T00:00:00Z'][.='2' ]" |
| ,pre+"/int[@name='1976-07-05T00:00:00Z'][.='2' ]" |
| ,pre+"/int[@name='1976-07-06T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-07T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-08T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-09T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-10T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-11T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-12T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-13T00:00:00Z'][.='2' ]" |
| ,pre+"/int[@name='1976-07-14T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-15T00:00:00Z'][.='1' ]" |
| // |
| ,meta+"/int[@name='before' ][.='1']" |
| ,meta+"/int[@name='after' ][.='1']" |
| ,meta+"/int[@name='between'][.='8']" |
| ); |
| |
| assertQ("checking counts for upper & edge", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,p, f |
| ,p+".start", "1976-07-01T00:00:00.000Z" |
| ,p+".end", "1976-07-16T00:00:00.000Z" |
| ,p+".gap", "+1DAY" |
| ,p+".other", "all" |
| ,p+".include", "upper" |
| ,p+".include", "edge" |
| ) |
| // 15 days + pre+post+inner = 18 |
| ,"*[count("+pre+"/int)=15]" |
| ,pre+"/int[@name='1976-07-01T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-02T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-03T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-04T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-05T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-06T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-07T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-08T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-09T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-10T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-11T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-12T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-13T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-14T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-15T00:00:00Z'][.='1' ]" |
| // |
| ,meta+"/int[@name='before' ][.='1']" |
| ,meta+"/int[@name='after' ][.='1']" |
| ,meta+"/int[@name='between'][.='8']" |
| ); |
| |
| assertQ("checking counts for upper & outer", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,p, f |
| ,p+".start", "1976-07-01T00:00:00.000Z" |
| ,p+".end", "1976-07-13T00:00:00.000Z" // smaller now |
| ,p+".gap", "+1DAY" |
| ,p+".other", "all" |
| ,p+".include", "upper" |
| ,p+".include", "outer" |
| ) |
| // 12 days + pre+post+inner = 15 |
| ,"*[count("+pre+"/int)=12]" |
| ,pre+"/int[@name='1976-07-01T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-02T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-03T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-04T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-05T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-06T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-07T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-08T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-09T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-10T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-11T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-12T00:00:00Z'][.='1' ]" |
| // |
| ,meta+"/int[@name='before' ][.='2']" |
| ,meta+"/int[@name='after' ][.='4']" |
| ,meta+"/int[@name='between'][.='5']" |
| ); |
| |
| assertQ("checking counts for lower & edge", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,p, f |
| ,p+".start", "1976-07-01T00:00:00.000Z" |
| ,p+".end", "1976-07-13T00:00:00.000Z" // smaller now |
| ,p+".gap", "+1DAY" |
| ,p+".other", "all" |
| ,p+".include", "lower" |
| ,p+".include", "edge" |
| ) |
| // 12 days + pre+post+inner = 15 |
| ,"*[count("+pre+"/int)=12]" |
| ,pre+"/int[@name='1976-07-01T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-02T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-03T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-04T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-05T00:00:00Z'][.='2' ]" |
| ,pre+"/int[@name='1976-07-06T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-07T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-08T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-09T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-10T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-11T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-12T00:00:00Z'][.='1' ]" |
| // |
| ,meta+"/int[@name='before' ][.='1']" |
| ,meta+"/int[@name='after' ][.='3']" |
| ,meta+"/int[@name='between'][.='6']" |
| ); |
| |
| assertQ("checking counts for lower & outer", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,p, f |
| ,p+".start", "1976-07-01T00:00:00.000Z" |
| ,p+".end", "1976-07-13T00:00:00.000Z" // smaller now |
| ,p+".gap", "+1DAY" |
| ,p+".other", "all" |
| ,p+".include", "lower" |
| ,p+".include", "outer" |
| ) |
| // 12 days + pre+post+inner = 15 |
| ,"*[count("+pre+"/int)=12]" |
| ,pre+"/int[@name='1976-07-01T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-02T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-03T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-04T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-05T00:00:00Z'][.='2' ]" |
| ,pre+"/int[@name='1976-07-06T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-07T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-08T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-09T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-10T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-11T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-12T00:00:00Z'][.='0']" |
| // |
| ,meta+"/int[@name='before' ][.='2']" |
| ,meta+"/int[@name='after' ][.='4']" |
| ,meta+"/int[@name='between'][.='5']" |
| ); |
| |
| assertQ("checking counts for lower & edge & outer", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,p, f |
| ,p+".start", "1976-07-01T00:00:00.000Z" |
| ,p+".end", "1976-07-13T00:00:00.000Z" // smaller now |
| ,p+".gap", "+1DAY" |
| ,p+".other", "all" |
| ,p+".include", "lower" |
| ,p+".include", "edge" |
| ,p+".include", "outer" |
| ) |
| // 12 days + pre+post+inner = 15 |
| ,"*[count("+pre+"/int)=12]" |
| ,pre+"/int[@name='1976-07-01T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-02T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-03T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-04T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-05T00:00:00Z'][.='2' ]" |
| ,pre+"/int[@name='1976-07-06T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-07T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-08T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-09T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-10T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-11T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-12T00:00:00Z'][.='1' ]" |
| // |
| ,meta+"/int[@name='before' ][.='2']" |
| ,meta+"/int[@name='after' ][.='4']" |
| ,meta+"/int[@name='between'][.='6']" |
| ); |
| |
| assertQ("checking counts for all", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,p, f |
| ,p+".start", "1976-07-01T00:00:00.000Z" |
| ,p+".end", "1976-07-13T00:00:00.000Z" // smaller now |
| ,p+".gap", "+1DAY" |
| ,p+".other", "all" |
| ,p+".include", "all" |
| ) |
| // 12 days + pre+post+inner = 15 |
| ,"*[count("+pre+"/int)=12]" |
| ,pre+"/int[@name='1976-07-01T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-02T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-03T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-04T00:00:00Z'][.='2' ]" |
| ,pre+"/int[@name='1976-07-05T00:00:00Z'][.='2' ]" |
| ,pre+"/int[@name='1976-07-06T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-07T00:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-08T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-09T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-10T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-11T00:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-12T00:00:00Z'][.='1' ]" |
| // |
| ,meta+"/int[@name='before' ][.='2']" |
| ,meta+"/int[@name='after' ][.='4']" |
| ,meta+"/int[@name='between'][.='6']" |
| ); |
| } |
| |
| @Test |
| public void testDateRangeFacetsWithTz() { |
| helpTestDateRangeFacetsWithTz("a_tdt"); |
| } |
| |
| private void helpTestDateRangeFacetsWithTz(final String fieldName) { |
| final String p = "facet.range"; |
| final String b = "facet_ranges"; |
| final String f = fieldName; |
| final String c = "/lst[@name='counts']"; |
| final String pre = "//lst[@name='"+b+"']/lst[@name='"+f+"']" + c; |
| final String meta = pre + "/../"; |
| |
| final String TZ = "America/Los_Angeles"; |
| assumeTrue("Test requires JVM to know about about TZ: " + TZ, |
| TimeZoneUtils.KNOWN_TIMEZONE_IDS.contains(TZ)); |
| |
| assertQ("checking facet counts for fixed now, using TZ: " + TZ, |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,"NOW", "205078333000" // 1976-07-01T14:12:13.000Z |
| ,"TZ", TZ |
| ,p, f |
| ,p+".start", "NOW/MONTH" |
| ,p+".end", "NOW/MONTH+15DAYS" |
| ,p+".gap", "+1DAY" |
| ,p+".other", "all" |
| ,p+".include", "lower" |
| ) |
| // 15 days + pre+post+inner = 18 |
| ,"*[count("+pre+"/int)=15]" |
| ,pre+"/int[@name='1976-07-01T07:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-02T07:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-03T07:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-04T07:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-05T07:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-06T07:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-07T07:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-08T07:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-09T07:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-10T07:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-11T07:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-12T07:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-13T07:00:00Z'][.='1' ]" |
| ,pre+"/int[@name='1976-07-14T07:00:00Z'][.='0']" |
| ,pre+"/int[@name='1976-07-15T07:00:00Z'][.='1' ]" |
| // |
| ,meta+"/int[@name='before' ][.='2']" |
| ,meta+"/int[@name='after' ][.='1']" |
| ,meta+"/int[@name='between'][.='7']" |
| ); |
| |
| // NOTE: the counts should all be zero, what we really care about |
| // is that the computed lower bounds take into account DST change |
| assertQ("checking facet counts arround DST change for TZ: " + TZ, |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,"NOW", "1288606136000" // 2010-11-01T10:08:56.235Z |
| ,"TZ", TZ |
| ,p, f |
| ,p+".start", "NOW/MONTH" |
| ,p+".end", "NOW/MONTH+15DAYS" |
| ,p+".gap", "+1DAY" |
| ,p+".other", "all" |
| ,p+".include", "lower" |
| ) |
| // 15 days + pre+post+inner = 18 |
| ,"*[count("+pre+"/int)=15]" |
| ,pre+"/int[@name='2010-11-01T07:00:00Z'][.='0']" |
| ,pre+"/int[@name='2010-11-02T07:00:00Z'][.='0']" |
| ,pre+"/int[@name='2010-11-03T07:00:00Z'][.='0']" |
| ,pre+"/int[@name='2010-11-04T07:00:00Z'][.='0']" |
| ,pre+"/int[@name='2010-11-05T07:00:00Z'][.='0']" |
| ,pre+"/int[@name='2010-11-06T07:00:00Z'][.='0']" |
| ,pre+"/int[@name='2010-11-07T07:00:00Z'][.='0']" |
| ,pre+"/int[@name='2010-11-08T08:00:00Z'][.='0']" // BOOM! |
| ,pre+"/int[@name='2010-11-09T08:00:00Z'][.='0']" |
| ,pre+"/int[@name='2010-11-10T08:00:00Z'][.='0']" |
| ,pre+"/int[@name='2010-11-11T08:00:00Z'][.='0']" |
| ,pre+"/int[@name='2010-11-12T08:00:00Z'][.='0']" |
| ,pre+"/int[@name='2010-11-13T08:00:00Z'][.='0']" |
| ,pre+"/int[@name='2010-11-14T08:00:00Z'][.='0']" |
| ,pre+"/int[@name='2010-11-15T08:00:00Z'][.='0']" |
| ); |
| |
| } |
| |
| @Test |
| public void testNumericRangeFacetsTrieFloat() { |
| helpTestFractionalNumberRangeFacets("range_facet_f"); |
| } |
| @Test |
| public void testNumericRangeFacetsTrieDouble() { |
| helpTestFractionalNumberRangeFacets("range_facet_d"); |
| } |
| |
| @Test |
| public void testNumericRangeFacetsTrieFloatDocValues() { |
| helpTestFractionalNumberRangeFacets("range_facet_f", FacetRangeMethod.DV); |
| } |
| @Test |
| public void testNumericRangeFacetsTrieDoubleDocValues() { |
| helpTestFractionalNumberRangeFacets("range_facet_d", FacetRangeMethod.DV); |
| } |
| |
| @Test |
| public void testNumericRangeFacetsOverflowTrieDouble() { |
| helpTestNumericRangeFacetsDoubleOverflow("range_facet_d", FacetRangeMethod.FILTER); |
| } |
| |
| @Test |
| public void testNumericRangeFacetsOverflowTrieDoubleDocValue() { |
| helpTestNumericRangeFacetsDoubleOverflow("range_facet_d", FacetRangeMethod.DV); |
| } |
| |
| private void helpTestNumericRangeFacetsDoubleOverflow(final String fieldName, final FacetRangeMethod method) { |
| final String f = fieldName; |
| final String pre = "//lst[@name='facet_ranges']/lst[@name='"+f+"']/lst[@name='counts']"; |
| final String meta = pre + "/../"; |
| |
| String start = "0.0"; |
| String gap = Double.toString(Float.MAX_VALUE ); |
| String end = Double.toString(((double) Float.MAX_VALUE) * 3D); |
| String mid = Double.toString(((double) Float.MAX_VALUE) * 2D); |
| |
| assertQ(f+": checking counts for lower", |
| req( "q", "id_i1:[30 TO 60]" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,"facet.range", f |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start", start |
| ,"facet.range.end", end |
| ,"facet.range.gap", gap |
| ,"facet.range.other", "all" |
| ,"facet.range.include", "lower" |
| ) |
| ,"*[count("+pre+"/int)=3]" |
| ,pre+"/int[@name='"+start+"'][.='6' ]" |
| ,pre+"/int[@name='"+mid+"'][.='0' ]" |
| // |
| ,meta+"/double[@name='end' ][.='"+end+"']" |
| ,meta+"/int[@name='before' ][.='0']" |
| ,meta+"/int[@name='after' ][.='0']" |
| ,meta+"/int[@name='between'][.='6']" |
| ); |
| } |
| |
| private void helpTestFractionalNumberRangeFacets(final String fieldName) { |
| helpTestFractionalNumberRangeFacets(fieldName, FacetRangeMethod.FILTER); |
| } |
| private void helpTestFractionalNumberRangeFacets(final String fieldName, FacetRangeMethod method) { |
| |
| final String f = fieldName; |
| final String pre = "//lst[@name='facet_ranges']/lst[@name='"+f+"']/lst[@name='counts']"; |
| final String meta = pre + "/../"; |
| |
| assertQ(f+": checking counts for lower", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,"facet.range", f |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start", "10" |
| ,"facet.range.end", "50" |
| ,"facet.range.gap", "10" |
| ,"facet.range.other", "all" |
| ,"facet.range.include", "lower" |
| ) |
| ,"*[count("+pre+"/int)=4]" |
| ,pre+"/int[@name='10.0'][.='1' ]" |
| ,pre+"/int[@name='20.0'][.='3' ]" |
| ,pre+"/int[@name='30.0'][.='2' ]" |
| ,pre+"/int[@name='40.0'][.='0' ]" |
| // |
| ,meta+"/int[@name='before' ][.='0']" |
| ,meta+"/int[@name='after' ][.='0']" |
| ,meta+"/int[@name='between'][.='6']" |
| ); |
| |
| assertQ(f + ":checking counts for upper", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,"facet.range", f |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start", "10" |
| ,"facet.range.end", "50" |
| ,"facet.range.gap", "10" |
| ,"facet.range.other", "all" |
| ,"facet.range.include", "upper" |
| ) |
| ,"*[count("+pre+"/int)=4]" |
| ,pre+"/int[@name='10.0'][.='2' ]" |
| ,pre+"/int[@name='20.0'][.='3' ]" |
| ,pre+"/int[@name='30.0'][.='1' ]" |
| ,pre+"/int[@name='40.0'][.='0' ]" |
| // |
| ,meta+"/int[@name='before' ][.='0']" |
| ,meta+"/int[@name='after' ][.='0']" |
| ,meta+"/int[@name='between'][.='6']" |
| ); |
| |
| assertQ(f + ":checking counts for lower & upper", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,"facet.range", f |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start", "10" |
| ,"facet.range.end", "50" |
| ,"facet.range.gap", "10" |
| ,"facet.range.other", "all" |
| ,"facet.range.include", "upper" |
| ,"facet.range.include", "lower" |
| ) |
| ,"*[count("+pre+"/int)=4]" |
| ,pre+"/int[@name='10.0'][.='2' ]" |
| ,pre+"/int[@name='20.0'][.='4' ]" |
| ,pre+"/int[@name='30.0'][.='2' ]" |
| ,pre+"/int[@name='40.0'][.='0' ]" |
| // |
| ,meta+"/int[@name='before' ][.='0']" |
| ,meta+"/int[@name='after' ][.='0']" |
| ,meta+"/int[@name='between'][.='6']" |
| ); |
| |
| assertQ(f + ": checking counts for upper & edge", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,"facet.range", f |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start", "20" |
| ,"facet.range.end", "50" |
| ,"facet.range.gap", "10" |
| ,"facet.range.other", "all" |
| ,"facet.range.include", "upper" |
| ,"facet.range.include", "edge" |
| ) |
| ,"*[count("+pre+"/int)=3]" |
| ,pre+"/int[@name='20.0'][.='4' ]" |
| ,pre+"/int[@name='30.0'][.='1' ]" |
| ,pre+"/int[@name='40.0'][.='0' ]" |
| // |
| ,meta+"/int[@name='before' ][.='1']" |
| ,meta+"/int[@name='after' ][.='0']" |
| ,meta+"/int[@name='between'][.='5']" |
| ); |
| |
| assertQ(f + ": checking counts for upper & outer", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,"facet.range", f |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start", "10" |
| ,"facet.range.end", "30" |
| ,"facet.range.gap", "10" |
| ,"facet.range.other", "all" |
| ,"facet.range.include", "upper" |
| ,"facet.range.include", "outer" |
| ) |
| ,"*[count("+pre+"/int)=2]" |
| ,pre+"/int[@name='10.0'][.='2' ]" |
| ,pre+"/int[@name='20.0'][.='3' ]" |
| // |
| ,meta+"/int[@name='before' ][.='0']" |
| ,meta+"/int[@name='after' ][.='2']" |
| ,meta+"/int[@name='between'][.='5']" |
| ); |
| |
| assertQ(f + ": checking counts for lower & edge", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,"facet.range", f |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start", "10" |
| ,"facet.range.end", "30" |
| ,"facet.range.gap", "10" |
| ,"facet.range.other", "all" |
| ,"facet.range.include", "lower" |
| ,"facet.range.include", "edge" |
| ) |
| ,"*[count("+pre+"/int)=2]" |
| ,pre+"/int[@name='10.0'][.='1' ]" |
| ,pre+"/int[@name='20.0'][.='4' ]" |
| // |
| ,meta+"/int[@name='before' ][.='0']" |
| ,meta+"/int[@name='after' ][.='1']" |
| ,meta+"/int[@name='between'][.='5']" |
| ); |
| |
| assertQ(f + ": checking counts for lower & outer", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,"facet.range", f |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start", "20" |
| ,"facet.range.end", "40" |
| ,"facet.range.gap", "10" |
| ,"facet.range.other", "all" |
| ,"facet.range.include", "lower" |
| ,"facet.range.include", "outer" |
| ) |
| ,"*[count("+pre+"/int)=2]" |
| ,pre+"/int[@name='20.0'][.='3' ]" |
| ,pre+"/int[@name='30.0'][.='2' ]" |
| // |
| ,meta+"/int[@name='before' ][.='2']" |
| ,meta+"/int[@name='after' ][.='0']" |
| ,meta+"/int[@name='between'][.='5']" |
| ); |
| |
| assertQ(f + ": checking counts for lower & edge & outer", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,"facet.range", f |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start", "20" |
| ,"facet.range.end", "35.3" |
| ,"facet.range.gap", "10" |
| ,"facet.range.other", "all" |
| ,"facet.range.hardend", "true" |
| ,"facet.range.include", "lower" |
| ,"facet.range.include", "edge" |
| ,"facet.range.include", "outer" |
| ) |
| ,"*[count("+pre+"/int)=2]" |
| ,pre+"/int[@name='20.0'][.='3' ]" |
| ,pre+"/int[@name='30.0'][.='2' ]" |
| // |
| ,meta+"/int[@name='before' ][.='2']" |
| ,meta+"/int[@name='after' ][.='1']" |
| ,meta+"/int[@name='between'][.='5']" |
| ); |
| |
| assertQ(f + ": checking counts for include all", |
| req( "q", "*:*" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,"facet.range", f |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start", "20" |
| ,"facet.range.end", "35.3" |
| ,"facet.range.gap", "10" |
| ,"facet.range.other", "all" |
| ,"facet.range.hardend", "true" |
| ,"facet.range.include", "all" |
| ) |
| ,"*[count("+pre+"/int)=2]" |
| ,pre+"/int[@name='20.0'][.='4' ]" |
| ,pre+"/int[@name='30.0'][.='2' ]" |
| // |
| ,meta+"/int[@name='before' ][.='2']" |
| ,meta+"/int[@name='after' ][.='1']" |
| ,meta+"/int[@name='between'][.='5']" |
| ); |
| } |
| |
| @Test |
| public void testNumericRangeFacetsTrieInt() { |
| helpTestWholeNumberRangeFacets("id_i1"); |
| } |
| @Test |
| public void testNumericRangeFacetsTrieLong() { |
| helpTestWholeNumberRangeFacets("range_facet_l"); |
| } |
| |
| @Test |
| public void testNumericRangeFacetsTrieIntDocValues() { |
| helpTestWholeNumberRangeFacets("id_i1", FacetRangeMethod.DV); |
| } |
| |
| @Test |
| public void testNumericRangeFacetsTrieLongDocValues() { |
| helpTestWholeNumberRangeFacets("range_facet_l", FacetRangeMethod.DV); |
| } |
| |
| @Test |
| public void testNumericRangeFacetsOverflowTrieLong() { |
| helpTestNumericRangeFacetsLongOverflow("range_facet_l", FacetRangeMethod.FILTER); |
| } |
| |
| @Test |
| public void testNumericRangeFacetsOverflowTrieLongDocValues() { |
| helpTestNumericRangeFacetsLongOverflow("range_facet_l", FacetRangeMethod.DV); |
| } |
| |
| private void helpTestNumericRangeFacetsLongOverflow(final String fieldName, final FacetRangeMethod method) { |
| final String f = fieldName; |
| final String pre = "//lst[@name='facet_ranges']/lst[@name='"+f+"']/lst[@name='counts']"; |
| final String meta = pre + "/../"; |
| |
| String start = "0"; |
| String gap = Long.toString(Integer.MAX_VALUE ); |
| String end = Long.toString( ((long)Integer.MAX_VALUE) * 3L ); |
| String mid = Long.toString(((long)Integer.MAX_VALUE) * 2L ); |
| |
| assertQ(f+": checking counts for lower", |
| req( "q", "id_i1:[30 TO 60]" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,"facet.range", f |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start", start |
| ,"facet.range.end", end |
| ,"facet.range.gap", gap |
| ,"facet.range.other", "all" |
| ,"facet.range.include", "lower" |
| ) |
| ,"*[count("+pre+"/int)=3]" |
| ,pre+"/int[@name='"+start+"'][.='6' ]" |
| ,pre+"/int[@name='"+mid+"'][.='0' ]" |
| // |
| ,meta+"/long[@name='end' ][.='"+end+"']" |
| ,meta+"/int[@name='before' ][.='0']" |
| ,meta+"/int[@name='after' ][.='0']" |
| ,meta+"/int[@name='between'][.='6']" |
| ); |
| } |
| |
| private void helpTestWholeNumberRangeFacets(final String fieldName) { |
| helpTestWholeNumberRangeFacets(fieldName, FacetRangeMethod.FILTER); |
| } |
| |
| private void helpTestWholeNumberRangeFacets(final String fieldName, FacetRangeMethod method) { |
| |
| // the float test covers a lot of the weird edge cases |
| // here we just need some basic sanity checking of the parsing |
| |
| final String f = fieldName; |
| final String pre = "//lst[@name='facet_ranges']/lst[@name='"+f+"']/lst[@name='counts']"; |
| final String meta = pre + "/../"; |
| |
| assertQ(f+": checking counts for lower", |
| req( "q", "id_i1:[30 TO 60]" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,"facet.range", f |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start", "35" |
| ,"facet.range.end", "50" |
| ,"facet.range.gap", "5" |
| ,"facet.range.other", "all" |
| ,"facet.range.include", "lower" |
| ) |
| ,"*[count("+pre+"/int)=3]" |
| ,pre+"/int[@name='35'][.='0' ]" |
| ,pre+"/int[@name='40'][.='3' ]" |
| ,pre+"/int[@name='45'][.='3' ]" |
| // |
| ,meta+"/int[@name='before' ][.='0']" |
| ,meta+"/int[@name='after' ][.='0']" |
| ,meta+"/int[@name='between'][.='6']" |
| ); |
| |
| assertQ(f + ":checking counts for upper", |
| req( "q", "id_i1:[30 TO 60]" |
| ,"rows", "0" |
| ,"facet", "true" |
| ,"facet.range", f |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start", "35" |
| ,"facet.range.end", "50" |
| ,"facet.range.gap", "5" |
| ,"facet.range.other", "all" |
| ,"facet.range.include", "upper" |
| ) |
| ,"*[count("+pre+"/int)=3]" |
| ,pre+"/int[@name='35'][.='0' ]" |
| ,pre+"/int[@name='40'][.='4' ]" |
| ,pre+"/int[@name='45'][.='2' ]" |
| // |
| ,meta+"/int[@name='before' ][.='0']" |
| ,meta+"/int[@name='after' ][.='0']" |
| ,meta+"/int[@name='between'][.='6']" |
| ); |
| |
| } |
| |
| static void indexFacetSingleValued() { |
| indexFacets("40","t_s1"); |
| } |
| |
| @Test |
| public void testFacetSingleValued() { |
| doFacets("t_s1"); |
| } |
| @Test |
| public void testFacetSingleValuedFcs() { |
| doFacets("t_s1","facet.method","fcs"); |
| } |
| |
| static void indexFacets(String idPrefix, String f) { |
| add_doc("id", idPrefix+"1", f, "A"); |
| add_doc("id", idPrefix+"2", f, "B"); |
| add_doc("id", idPrefix+"3", f, "C"); |
| add_doc("id", idPrefix+"4", f, "C"); |
| add_doc("id", idPrefix+"5", f, "D"); |
| add_doc("id", idPrefix+"6", f, "E"); |
| add_doc("id", idPrefix+"7", f, "E"); |
| add_doc("id", idPrefix+"8", f, "E"); |
| add_doc("id", idPrefix+"9", f, "F"); |
| add_doc("id", idPrefix+"10", f, "G"); |
| add_doc("id", idPrefix+"11", f, "G"); |
| add_doc("id", idPrefix+"12", f, "G"); |
| add_doc("id", idPrefix+"13", f, "G"); |
| add_doc("id", idPrefix+"14", f, "G"); |
| } |
| |
| public void doFacets(String f, String... params) { |
| String pre = "//lst[@name='"+f+"']"; |
| String notc = "id:[* TO *] -"+f+":C"; |
| |
| |
| assertQ("check counts for unlimited facet", |
| req(params, "q", "id:[* TO *]", "indent","true" |
| ,"facet", "true" |
| ,"facet.field", f |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=7]" |
| |
| ,pre+"/int[@name='G'][.='5']" |
| ,pre+"/int[@name='E'][.='3']" |
| ,pre+"/int[@name='C'][.='2']" |
| |
| ,pre+"/int[@name='A'][.='1']" |
| ,pre+"/int[@name='B'][.='1']" |
| ,pre+"/int[@name='D'][.='1']" |
| ,pre+"/int[@name='F'][.='1']" |
| ); |
| |
| assertQ("check counts for facet with generous limit", |
| req(params, "q", "id:[* TO *]" |
| ,"facet", "true" |
| ,"facet.limit", "100" |
| ,"facet.field", f |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=7]" |
| |
| ,pre+"/int[1][@name='G'][.='5']" |
| ,pre+"/int[2][@name='E'][.='3']" |
| ,pre+"/int[3][@name='C'][.='2']" |
| |
| ,pre+"/int[@name='A'][.='1']" |
| ,pre+"/int[@name='B'][.='1']" |
| ,pre+"/int[@name='D'][.='1']" |
| ,pre+"/int[@name='F'][.='1']" |
| ); |
| |
| assertQ("check counts for limited facet", |
| req(params, "q", "id:[* TO *]" |
| ,"facet", "true" |
| ,"facet.limit", "2" |
| ,"facet.field", f |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=2]" |
| |
| ,pre+"/int[1][@name='G'][.='5']" |
| ,pre+"/int[2][@name='E'][.='3']" |
| ); |
| |
| assertQ("check offset", |
| req(params, "q", "id:[* TO *]" |
| ,"facet", "true" |
| ,"facet.offset", "1" |
| ,"facet.limit", "1" |
| ,"facet.field", f |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=1]" |
| |
| ,pre+"/int[1][@name='E'][.='3']" |
| ); |
| |
| assertQ("test sorted facet paging with zero (don't count in limit)", |
| req(params, "q", "id:[* TO *]" |
| ,"fq",notc |
| ,"facet", "true" |
| ,"facet.field", f |
| ,"facet.mincount","1" |
| ,"facet.offset","0" |
| ,"facet.limit","6" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=6]" |
| ,pre+"/int[1][@name='G'][.='5']" |
| ,pre+"/int[2][@name='E'][.='3']" |
| ,pre+"/int[3][@name='A'][.='1']" |
| ,pre+"/int[4][@name='B'][.='1']" |
| ,pre+"/int[5][@name='D'][.='1']" |
| ,pre+"/int[6][@name='F'][.='1']" |
| ); |
| |
| assertQ("test sorted facet paging with zero (test offset correctness)", |
| req(params, "q", "id:[* TO *]" |
| ,"fq",notc |
| ,"facet", "true" |
| ,"facet.field", f |
| ,"facet.mincount","1" |
| ,"facet.offset","3" |
| ,"facet.limit","2" |
| ,"facet.sort","count" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=2]" |
| ,pre+"/int[1][@name='B'][.='1']" |
| ,pre+"/int[2][@name='D'][.='1']" |
| ); |
| |
| assertQ("test facet unsorted paging", |
| req(params, "q", "id:[* TO *]" |
| ,"fq",notc |
| ,"facet", "true" |
| ,"facet.field", f |
| ,"facet.mincount","1" |
| ,"facet.offset","0" |
| ,"facet.limit","6" |
| ,"facet.sort","index" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=6]" |
| ,pre+"/int[1][@name='A'][.='1']" |
| ,pre+"/int[2][@name='B'][.='1']" |
| ,pre+"/int[3][@name='D'][.='1']" |
| ,pre+"/int[4][@name='E'][.='3']" |
| ,pre+"/int[5][@name='F'][.='1']" |
| ,pre+"/int[6][@name='G'][.='5']" |
| ); |
| |
| assertQ("test facet unsorted paging", |
| req(params, "q", "id:[* TO *]" |
| ,"fq",notc |
| ,"facet", "true" |
| ,"facet.field", f |
| ,"facet.mincount","1" |
| ,"facet.offset","3" |
| ,"facet.limit","2" |
| ,"facet.sort","index" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=2]" |
| ,pre+"/int[1][@name='E'][.='3']" |
| ,pre+"/int[2][@name='F'][.='1']" |
| ); |
| |
| assertQ("test facet unsorted paging, mincount=2", |
| req(params, "q", "id:[* TO *]" |
| ,"fq",notc |
| ,"facet", "true" |
| ,"facet.field", f |
| ,"facet.mincount","2" |
| ,"facet.offset","1" |
| ,"facet.limit","2" |
| ,"facet.sort","index" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=1]" |
| ,pre+"/int[1][@name='G'][.='5']" |
| ); |
| } |
| |
| |
| static void indexFacetPrefixMultiValued() { |
| indexFacetPrefix("50","t_s","","ignore_s"); |
| } |
| |
| @Test |
| public void testFacetPrefixMultiValued() { |
| doFacetPrefix("t_s", null, "", "facet.method","enum"); |
| doFacetPrefix("t_s", null, "", "facet.method", "enum", "facet.enum.cache.minDf", "3"); |
| doFacetPrefix("t_s", null, "", "facet.method", "enum", "facet.enum.cache.minDf", "100"); |
| doFacetPrefix("t_s", null, "", "facet.method", "fc"); |
| doFacetExistsPrefix("t_s", null, ""); |
| doFacetExistsPrefix("t_s", null, "", "facet.enum.cache.minDf", "3"); |
| doFacetExistsPrefix("t_s", null, "", "facet.enum.cache.minDf", "100"); |
| } |
| |
| @Test |
| public void testFacetExistsShouldThrowExceptionForMincountGreaterThanOne () throws Exception { |
| final String f = "t_s"; |
| final List<String> msg = Arrays.asList("facet.mincount", "facet.exists", f); |
| Collections.shuffle(msg, random()); |
| assertQEx("checking global method or per field", msg.get(0), |
| req("q", "id:[* TO *]" |
| ,"indent","on" |
| ,"facet","true" |
| , random().nextBoolean() ? "facet.exists": "f."+f+".facet.exists", "true" |
| ,"facet.field", f |
| , random().nextBoolean() ? "facet.mincount" : "f."+f+".facet.mincount" , |
| "" + (2+random().nextInt(Integer.MAX_VALUE-2)) |
| ) |
| , ErrorCode.BAD_REQUEST); |
| |
| assertQ("overriding per field", |
| req("q", "id:[* TO *]" |
| ,"indent","on" |
| ,"facet","true" |
| ,"facet.exists", "true" |
| ,"f."+f+".facet.exists", "false" |
| ,"facet.field", f |
| ,"facet.mincount",""+(2+random().nextInt(Integer.MAX_VALUE-2)) |
| ), |
| "//lst[@name='facet_fields']/lst[@name='"+f+"']"); |
| |
| assertQ("overriding per field", |
| req("q", "id:[* TO *]" |
| ,"indent","on" |
| ,"facet","true" |
| ,"facet.exists", "true" |
| ,"facet.field", f |
| ,"facet.mincount",""+(2+random().nextInt(Integer.MAX_VALUE-2)) |
| ,"f."+f+".facet.mincount", random().nextBoolean() ? "0":"1" |
| ), |
| "//lst[@name='facet_fields']/lst[@name='"+f+"']"); |
| |
| } |
| |
| static void indexFacetPrefixSingleValued() { |
| indexFacetPrefix("60","tt_s1","","ignore_s"); |
| } |
| |
| @Test |
| public void testFacetPrefixSingleValued() { |
| doFacetPrefix("tt_s1", null, ""); |
| } |
| |
| @Test |
| public void testFacetPrefixSingleValuedFcs() { |
| doFacetPrefix("tt_s1", null, "", "facet.method","fcs"); |
| doFacetPrefix("tt_s1", "{!threads=0}", "", "facet.method","fcs"); // direct execution |
| doFacetPrefix("tt_s1", "{!threads=-1}", "", "facet.method","fcs"); // default / unlimited threads |
| doFacetPrefix("tt_s1", "{!threads=2}", "", "facet.method","fcs"); // specific number of threads |
| } |
| |
| @Test |
| public void testFacetExclude() { |
| for (String method : new String[] {"enum", "fcs", "fc", "uif"}) { |
| doFacetExclude("contains_s1", "contains_group_s1", "Astra", "facet.method", method); |
| } |
| } |
| |
| private void doFacetExclude(String f, String g, String termSuffix, String... params) { |
| String indent="on"; |
| String pre = "//lst[@name='"+f+"']"; |
| |
| final SolrQueryRequest req = req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.field", f |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.excludeTerms","B,BBB"+termSuffix |
| ); |
| |
| assertQ("test facet.exclude", |
| req |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=10]" |
| ,pre+"/int[1][@name='BBB'][.='3']" |
| ,pre+"/int[2][@name='CCC'][.='3']" |
| ,pre+"/int[3][@name='CCC"+termSuffix+"'][.='3']" |
| ,pre+"/int[4][@name='BB'][.='2']" |
| ,pre+"/int[5][@name='BB"+termSuffix+"'][.='2']" |
| ,pre+"/int[6][@name='CC'][.='2']" |
| ,pre+"/int[7][@name='CC"+termSuffix+"'][.='2']" |
| ,pre+"/int[8][@name='AAA'][.='1']" |
| ,pre+"/int[9][@name='AAA"+termSuffix+"'][.='1']" |
| ,pre+"/int[10][@name='B"+termSuffix+"'][.='1']" |
| ); |
| |
| final SolrQueryRequest groupReq = req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.field", f |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.excludeTerms","B,BBB"+termSuffix |
| ,"group","true" |
| ,"group.field",g |
| ,"group.facet","true" |
| ,"facet.missing","true" |
| ); |
| |
| assertQ("test facet.exclude for grouped facets", |
| groupReq |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=11]" |
| ,pre+"/int[1][@name='CCC'][.='3']" |
| ,pre+"/int[2][@name='CCC"+termSuffix+"'][.='3']" |
| ,pre+"/int[3][@name='BBB'][.='2']" |
| ,pre+"/int[4][@name='AAA'][.='1']" |
| ,pre+"/int[5][@name='AAA"+termSuffix+"'][.='1']" |
| ,pre+"/int[6][@name='B"+termSuffix+"'][.='1']" |
| ,pre+"/int[7][@name='BB'][.='1']" |
| ,pre+"/int[8][@name='BB"+termSuffix+"'][.='1']" |
| ,pre+"/int[9][@name='CC'][.='1']" |
| ,pre+"/int[10][@name='CC"+termSuffix+"'][.='1']" |
| ,pre+"/int[11][.='1']" |
| ); |
| |
| ModifiableSolrParams modifiableSolrParams = new ModifiableSolrParams(groupReq.getParams()); |
| modifiableSolrParams.set("facet.limit", "0"); |
| groupReq.setParams(modifiableSolrParams); |
| |
| assertQ("test facet.exclude for grouped facets with facet.limit=0, facet.missing=true", |
| groupReq |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=1]" |
| ,pre+"/int[.='1']" |
| ); |
| } |
| |
| @Test |
| public void testFacetContainsAndExclude() { |
| for (String method : new String[] {"enum", "fcs", "fc", "uif"}) { |
| String contains = "BAst"; |
| String groupContains = "Ast"; |
| final boolean ignoreCase = random().nextBoolean(); |
| if (ignoreCase) { |
| contains = randomizeStringCasing(contains); |
| groupContains = randomizeStringCasing(groupContains); |
| doFacetContainsAndExclude("contains_s1", "contains_group_s1", "Astra", contains, groupContains, "facet.method", method, "facet.contains.ignoreCase", "true"); |
| } else { |
| doFacetContainsAndExclude("contains_s1", "contains_group_s1", "Astra", contains, groupContains, "facet.method", method); |
| } |
| } |
| } |
| |
| private String randomizeStringCasing(String str) { |
| final char[] characters = str.toCharArray(); |
| |
| for (int i = 0; i != characters.length; ++i) { |
| final boolean switchCase = random().nextBoolean(); |
| if (!switchCase) { |
| continue; |
| } |
| |
| final char c = str.charAt(i); |
| if (Character.isUpperCase(c)) { |
| characters[i] = Character.toLowerCase(c); |
| } else { |
| characters[i] = Character.toUpperCase(c); |
| } |
| } |
| |
| return new String(characters); |
| } |
| |
| private void doFacetContainsAndExclude(String f, String g, String termSuffix, String contains, String groupContains, String... params) { |
| String indent="on"; |
| String pre = "//lst[@name='"+f+"']"; |
| |
| final SolrQueryRequest req = req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.field", f |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.contains",contains |
| ,"facet.excludeTerms","BBB"+termSuffix |
| ); |
| |
| assertQ("test facet.contains with facet.exclude", |
| req |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=2]" |
| ,pre+"/int[1][@name='BB"+termSuffix+"'][.='2']" |
| ,pre+"/int[2][@name='B"+termSuffix+"'][.='1']" |
| ); |
| |
| final SolrQueryRequest groupReq = req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.field", f |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.contains",groupContains |
| ,"facet.excludeTerms","AAA"+termSuffix |
| ,"group","true" |
| ,"group.field",g |
| ,"group.facet","true" |
| ); |
| |
| assertQ("test facet.contains with facet.exclude for grouped facets", |
| groupReq |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=5]" |
| ,pre+"/int[1][@name='CCC"+termSuffix+"'][.='3']" |
| ,pre+"/int[2][@name='BBB"+termSuffix+"'][.='2']" |
| ,pre+"/int[3][@name='B"+termSuffix+"'][.='1']" |
| ,pre+"/int[4][@name='BB"+termSuffix+"'][.='1']" |
| ,pre+"/int[5][@name='CC"+termSuffix+"'][.='1']" |
| ); |
| } |
| |
| @Test |
| //@Ignore("SOLR-8466 - facet.method=uif ignores facet.contains") |
| public void testFacetContainsUif() { |
| doFacetContains("contains_s1", "contains_group_s1", "Astra", "BAst", "Ast", "facet.method", "uif"); |
| doFacetPrefix("contains_s1", null, "Astra", "facet.method", "uif", "facet.contains", "Ast"); |
| doFacetPrefix("contains_s1", null, "Astra", "facet.method", "uif", "facet.contains", "aST", "facet.contains.ignoreCase", "true"); |
| } |
| |
| static void indexFacetContains() { |
| indexFacetPrefix("70","contains_s1","","contains_group_s1"); |
| indexFacetPrefix("80","contains_s1","Astra","contains_group_s1"); |
| } |
| |
| @Test |
| public void testFacetContains() { |
| doFacetContains("contains_s1", "contains_group_s1", "Astra", "BAst", "Ast", "facet.method", "enum"); |
| doFacetContains("contains_s1", "contains_group_s1", "Astra", "BAst", "Ast", "facet.method", "fcs"); |
| doFacetContains("contains_s1", "contains_group_s1", "Astra", "BAst", "Ast", "facet.method", "fc"); |
| doFacetContains("contains_s1", "contains_group_s1", "Astra", "bAst", "ast", "facet.method", "enum", "facet.contains.ignoreCase", "true"); |
| doFacetContains("contains_s1", "contains_group_s1", "Astra", "baSt", "ast", "facet.method", "fcs", "facet.contains.ignoreCase", "true"); |
| doFacetContains("contains_s1", "contains_group_s1", "Astra", "basT", "ast", "facet.method", "fc", "facet.contains.ignoreCase", "true"); |
| doFacetPrefix("contains_s1", null, "Astra", "facet.method", "enum", "facet.contains", "Ast"); |
| doFacetPrefix("contains_s1", null, "Astra", "facet.method", "fcs", "facet.contains", "Ast"); |
| doFacetPrefix("contains_s1", null, "Astra", "facet.method", "fc", "facet.contains", "Ast"); |
| doFacetPrefix("contains_s1", null, "Astra", "facet.method", "enum", "facet.contains", "aSt", "facet.contains.ignoreCase", "true"); |
| doFacetPrefix("contains_s1", null, "Astra", "facet.method", "fcs", "facet.contains", "asT", "facet.contains.ignoreCase", "true"); |
| doFacetPrefix("contains_s1", null, "Astra", "facet.method", "fc", "facet.contains", "aST", "facet.contains.ignoreCase", "true"); |
| doFacetExistsPrefix("contains_s1", null, "Astra", "facet.contains", "Ast"); |
| } |
| |
| static void indexFacetPrefix(String idPrefix, String f, String termSuffix, String g) { |
| add_doc("id", idPrefix+"1", f, "AAA"+termSuffix, g, "A"); |
| add_doc("id", idPrefix+"2", f, "B"+termSuffix, g, "A"); |
| add_doc("id", idPrefix+"3", f, "BB"+termSuffix, g, "B"); |
| add_doc("id", idPrefix+"4", f, "BB"+termSuffix, g, "B"); |
| add_doc("id", idPrefix+"5", f, "BBB"+termSuffix, g, "B"); |
| add_doc("id", idPrefix+"6", f, "BBB"+termSuffix, g, "B"); |
| add_doc("id", idPrefix+"7", f, "BBB"+termSuffix, g, "C"); |
| add_doc("id", idPrefix+"8", f, "CC"+termSuffix, g, "C"); |
| add_doc("id", idPrefix+"9", f, "CC"+termSuffix, g, "C"); |
| add_doc("id", idPrefix+"10", f, "CCC"+termSuffix, g, "C"); |
| add_doc("id", idPrefix+"11", f, "CCC"+termSuffix, g, "D"); |
| add_doc("id", idPrefix+"12", f, "CCC"+termSuffix, g, "E"); |
| assertU(commit()); |
| } |
| |
| public void doFacetPrefix(String f, String local, String termSuffix, String... params) { |
| String indent="on"; |
| String pre = "//lst[@name='"+f+"']"; |
| String lf = local==null ? f : local+f; |
| |
| |
| assertQ("test facet.prefix middle, exact match first term", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.prefix","B" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=3]" |
| ,pre+"/int[1][@name='BBB"+termSuffix+"'][.='3']" |
| ,pre+"/int[2][@name='BB"+termSuffix+"'][.='2']" |
| ,pre+"/int[3][@name='B"+termSuffix+"'][.='1']" |
| ); |
| |
| assertQ("test facet.prefix middle, exact match first term, unsorted", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","100" |
| ,"facet.sort","index" |
| ,"facet.prefix","B" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=3]" |
| ,pre+"/int[1][@name='B"+termSuffix+"'][.='1']" |
| ,pre+"/int[2][@name='BB"+termSuffix+"'][.='2']" |
| ,pre+"/int[3][@name='BBB"+termSuffix+"'][.='3']" |
| ); |
| |
| assertQ("test facet.prefix middle, paging", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","1" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.prefix","B" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=2]" |
| ,pre+"/int[1][@name='BB"+termSuffix+"'][.='2']" |
| ,pre+"/int[2][@name='B"+termSuffix+"'][.='1']" |
| ); |
| |
| assertQ("test facet.prefix middle, paging", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","1" |
| ,"facet.limit","1" |
| ,"facet.sort","count" |
| ,"facet.prefix","B" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=1]" |
| ,pre+"/int[1][@name='BB"+termSuffix+"'][.='2']" |
| ); |
| |
| assertQ("test facet.prefix middle, paging", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","1" |
| ,"facet.limit","1" |
| ,"facet.sort","count" |
| ,"facet.prefix","B" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=1]" |
| ,pre+"/int[1][@name='BB"+termSuffix+"'][.='2']" |
| ); |
| |
| assertQ("test facet.prefix end, not exact match", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.prefix","C" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=2]" |
| ,pre+"/int[1][@name='CCC"+termSuffix+"'][.='3']" |
| ,pre+"/int[2][@name='CC"+termSuffix+"'][.='2']" |
| ); |
| |
| assertQ("test facet.prefix end, exact match", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.prefix","CC" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=2]" |
| ,pre+"/int[1][@name='CCC"+termSuffix+"'][.='3']" |
| ,pre+"/int[2][@name='CC"+termSuffix+"'][.='2']" |
| ); |
| |
| assertQ("test facet.prefix past end", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.prefix","X" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=0]" |
| ); |
| |
| assertQ("test facet.prefix past end", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","1" |
| ,"facet.limit","-1" |
| ,"facet.sort","count" |
| ,"facet.prefix","X" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=0]" |
| ); |
| |
| assertQ("test facet.prefix at start, exact match", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.prefix","AAA" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=1]" |
| ,pre+"/int[1][@name='AAA"+termSuffix+"'][.='1']" |
| ); |
| assertQ("test facet.prefix at Start, not exact match", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.prefix","AA" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=1]" |
| ,pre+"/int[1][@name='AAA"+termSuffix+"'][.='1']" |
| ); |
| assertQ("test facet.prefix at Start, not exact match", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.prefix","AA" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=1]" |
| ,pre+"/int[1][@name='AAA"+termSuffix+"'][.='1']" |
| ); |
| assertQ("test facet.prefix before start", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.prefix","999" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=0]" |
| ); |
| |
| assertQ("test facet.prefix before start", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","2" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.prefix","999" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=0]" |
| ); |
| |
| // test offset beyond what is collected internally in queue |
| assertQ( |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.field", lf |
| ,"facet.mincount","3" |
| ,"facet.offset","5" |
| ,"facet.limit","10" |
| ,"facet.sort","count" |
| ,"facet.prefix","CC" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=0]" |
| ); |
| } |
| |
| public void doFacetExistsPrefix(String f, String local, String termSuffix, String... params) { |
| String indent="on"; |
| String pre = "//lst[@name='"+f+"']"; |
| String lf = local==null ? f : local+f; |
| |
| assertQ("test field facet.method", |
| req(params, "q", "id:[* TO *]" |
| ,"indent", indent |
| ,"facet", "true" |
| ,"f."+lf+".facet.exists", "true" |
| ,"facet.field", lf |
| ,"facet.mincount", "0" |
| ,"facet.offset", "0" |
| ,"facet.limit", "100" |
| ,"facet.sort", "count" |
| ,"facet.prefix", "B" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=3]" |
| ,pre+"/int[1][@name='B"+termSuffix+"'][.='1']" |
| ,pre+"/int[2][@name='BB"+termSuffix+"'][.='1']" |
| ,pre+"/int[3][@name='BBB"+termSuffix+"'][.='1']" |
| ); |
| |
| assertQ("test facet.prefix middle, exact match first term", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.exists", "true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.prefix","B" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=3]" |
| ,pre+"/int[1][@name='B"+termSuffix+"'][.='1']" |
| ,pre+"/int[2][@name='BB"+termSuffix+"'][.='1']" |
| ,pre+"/int[3][@name='BBB"+termSuffix+"'][.='1']" |
| ); |
| |
| assertQ("test facet.prefix middle, exact match first term, unsorted", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.exists", "true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","100" |
| ,"facet.sort","index" |
| ,"facet.prefix","B" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=3]" |
| ,pre+"/int[1][@name='B"+termSuffix+"'][.='1']" |
| ,pre+"/int[2][@name='BB"+termSuffix+"'][.='1']" |
| ,pre+"/int[3][@name='BBB"+termSuffix+"'][.='1']" |
| ); |
| |
| assertQ("test facet.prefix middle, paging", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.exists", "true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","1" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.prefix","B" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=2]" |
| ,pre+"/int[1][@name='BB"+termSuffix+"'][.='1']" |
| ,pre+"/int[2][@name='BBB"+termSuffix+"'][.='1']" |
| ); |
| |
| assertQ("test facet.prefix middle, paging", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.exists", "true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","1" |
| ,"facet.limit","1" |
| ,"facet.sort","count" |
| ,"facet.prefix","B" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=1]" |
| ,pre+"/int[1][@name='BB"+termSuffix+"'][.='1']" |
| ); |
| |
| assertQ("test facet.prefix end, not exact match", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.exists", "true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.prefix","C" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=2]" |
| ,pre+"/int[1][@name='CC"+termSuffix+"'][.='1']" |
| ,pre+"/int[2][@name='CCC"+termSuffix+"'][.='1']" |
| ); |
| |
| assertQ("test facet.prefix end, exact match", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.exists", "true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.prefix","CC" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=2]" |
| ,pre+"/int[1][@name='CC"+termSuffix+"'][.='1']" |
| ,pre+"/int[2][@name='CCC"+termSuffix+"'][.='1']" |
| ); |
| |
| assertQ("test facet.prefix past end", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.exists", "true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.prefix","X" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=0]" |
| ); |
| |
| assertQ("test facet.prefix past end", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.exists", "true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","1" |
| ,"facet.limit","-1" |
| ,"facet.sort","count" |
| ,"facet.prefix","X" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=0]" |
| ); |
| |
| assertQ("test facet.prefix at start, exact match", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.exists", "true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.prefix","AAA" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=1]" |
| ,pre+"/int[1][@name='AAA"+termSuffix+"'][.='1']" |
| ); |
| assertQ("test facet.prefix at Start, not exact match", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.exists", "true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.prefix","AA" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=1]" |
| ,pre+"/int[1][@name='AAA"+termSuffix+"'][.='1']" |
| ); |
| assertQ("test facet.prefix before start", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.exists", "true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.prefix","999" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=0]" |
| ); |
| |
| assertQ("test facet.prefix before start", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.exists", "true" |
| ,"facet.field", lf |
| ,"facet.mincount","0" |
| ,"facet.offset","2" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.prefix","999" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=0]" |
| ); |
| |
| // test offset beyond what is collected internally in queue |
| assertQ( |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.exists", "true" |
| ,"facet.field", lf |
| ,"facet.mincount","1" |
| ,"facet.offset","5" |
| ,"facet.limit","10" |
| ,"facet.sort","count" |
| ,"facet.prefix","CC" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=0]" |
| ); |
| } |
| |
| public void doFacetContains(String f, String g, String termSuffix, String contains, String groupContains, String... params) { |
| String indent="on"; |
| String pre = "//lst[@name='"+f+"']"; |
| |
| assertQ("test facet.contains", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.field", f |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.contains",contains |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=3]" |
| ,pre+"/int[1][@name='BBB"+termSuffix+"'][.='3']" |
| ,pre+"/int[2][@name='BB"+termSuffix+"'][.='2']" |
| ,pre+"/int[3][@name='B"+termSuffix+"'][.='1']" |
| ); |
| |
| assertQ("test facet.contains for grouped facets", |
| req(params, "q", "id:[* TO *]" |
| ,"indent",indent |
| ,"facet","true" |
| ,"facet.field", f |
| ,"facet.mincount","0" |
| ,"facet.offset","0" |
| ,"facet.limit","100" |
| ,"facet.sort","count" |
| ,"facet.contains",groupContains |
| ,"group","true" |
| ,"group.field",g |
| ,"group.facet","true" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst/int)=6]" |
| ,pre+"/int[1][@name='CCC"+termSuffix+"'][.='3']" |
| ,pre+"/int[2][@name='BBB"+termSuffix+"'][.='2']" |
| ,pre+"/int[3][@name='AAA"+termSuffix+"'][.='1']" |
| ,pre+"/int[4][@name='B"+termSuffix+"'][.='1']" |
| ,pre+"/int[5][@name='BB"+termSuffix+"'][.='1']" |
| ,pre+"/int[6][@name='CC"+termSuffix+"'][.='1']" |
| ); |
| } |
| |
| /** |
| * kind of an absurd test because if there is an infinite loop, it |
| * would never finish -- but at least it ensures that <i>if</i> one of |
| * these requests return, they return an error |
| */ |
| public void testRangeFacetInfiniteLoopDetection() { |
| |
| for (String field : new String[] {"foo_f", "foo_d", "foo_i"}) { |
| assertQEx("no zero gap error: " + field, |
| req("q", "*:*", |
| "facet", "true", |
| "facet.range", field, |
| "facet.range.start", "23", |
| "facet.range.gap", "0", |
| "facet.range.end", "100"), |
| 400); |
| } |
| String field = "foo_dt"; |
| assertQEx("no zero gap error for facet.range: " + field, |
| req("q", "*:*", |
| "facet", "true", |
| "facet.range", field, |
| "facet.range.start", "NOW", |
| "facet.range.gap", "+0DAYS", |
| "facet.range.end", "NOW+10DAY"), |
| 400); |
| field = "foo_f"; |
| assertQEx("no float underflow error: " + field, |
| req("q", "*:*", |
| "facet", "true", |
| "facet.range", field, |
| "facet.range.start", "100000000000", |
| "facet.range.end", "100000086200", |
| "facet.range.gap", "2160"), |
| 400); |
| |
| field = "foo_d"; |
| assertQEx("no double underflow error: " + field, |
| req("q", "*:*", |
| "facet", "true", |
| "facet.range", field, |
| "facet.range.start", "9900000000000", |
| "facet.range.end", "9900000086200", |
| "facet.range.gap", "0.0003"), |
| 400); |
| } |
| |
| public void testRangeQueryHardEndParamFilter() { |
| doTestRangeQueryHardEndParam("range_facet_l", FacetRangeMethod.FILTER); |
| } |
| |
| public void testRangeQueryHardEndParamDv() { |
| doTestRangeQueryHardEndParam("range_facet_l", FacetRangeMethod.DV); |
| } |
| |
| private void doTestRangeQueryHardEndParam(String field, FacetRangeMethod method) { |
| assertQ("Test facet.range.hardend", |
| req("q", "id_i1:[42 TO 47]" |
| ,"facet","true" |
| ,"fl","id," + field |
| ,"facet.range", field |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start","43" |
| ,"facet.range.end","45" |
| ,"facet.range.gap","5" |
| ,"facet.range.hardend", "false" |
| ,"facet.range.other", "after" |
| ) |
| ,"*[count(//lst[@name='facet_ranges']/lst)=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts']/int)=1]" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts']/int[@name='43'][.='5']" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/long[@name='end'][.='48']" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='after'][.='0']" |
| ); |
| |
| assertQ("Test facet.range.hardend", |
| req("q", "id_i1:[42 TO 47]" |
| ,"facet","true" |
| ,"fl","id," + field |
| ,"facet.range", field |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start","43" |
| ,"facet.range.end","45" |
| ,"facet.range.gap","5" |
| ,"facet.range.hardend", "true" |
| ,"facet.range.other", "after" |
| ) |
| ,"*[count(//lst[@name='facet_ranges']/lst)=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts']/int)=1]" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts']/int[@name='43'][.='2']" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/long[@name='end'][.='45']" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='after'][.='3']" |
| ); |
| |
| } |
| |
| public void testRangeQueryOtherParamFilter() { |
| doTestRangeQueryOtherParam("range_facet_l", FacetRangeMethod.FILTER); |
| } |
| |
| public void testRangeQueryOtherParamDv() { |
| doTestRangeQueryOtherParam("range_facet_l", FacetRangeMethod.DV); |
| } |
| |
| private void doTestRangeQueryOtherParam(String field, FacetRangeMethod method) { |
| |
| assertQ("Test facet.range.other", |
| req("q", "id_i1:[42 TO 47]" |
| ,"facet","true" |
| ,"fl","id," + field |
| ,"facet.range", field |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start","43" |
| ,"facet.range.end","45" |
| ,"facet.range.gap","1" |
| ,"facet.range.other", FacetRangeOther.BEFORE.toString() |
| ) |
| ,"*[count(//lst[@name='facet_ranges']/lst)=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts']/int)=2]" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='before'][.='1']" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='after'])=0]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='between'])=0]" |
| ); |
| |
| assertQ("Test facet.range.other", |
| req("q", "id_i1:[42 TO 47]" |
| ,"facet","true" |
| ,"fl","id," + field |
| ,"facet.range", field |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start","43" |
| ,"facet.range.end","45" |
| ,"facet.range.gap","1" |
| ,"facet.range.other", FacetRangeOther.AFTER.toString() |
| ) |
| ,"*[count(//lst[@name='facet_ranges']/lst)=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts']/int)=2]" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='after'][.='3']" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='between'])=0]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='before'])=0]" |
| ); |
| |
| assertQ("Test facet.range.other", |
| req("q", "id_i1:[42 TO 47]" |
| ,"facet","true" |
| ,"fl","id," + field |
| ,"facet.range", field |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start","43" |
| ,"facet.range.end","45" |
| ,"facet.range.gap","1" |
| ,"facet.range.other",FacetRangeOther.BETWEEN.toString() |
| ) |
| ,"*[count(//lst[@name='facet_ranges']/lst)=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts']/int)=2]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='after'])=0]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='before'])=0]" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='between'][.='2']" |
| ); |
| |
| assertQ("Test facet.range.other", |
| req("q", "id_i1:[42 TO 47]" |
| ,"facet","true" |
| ,"fl","id," + field |
| ,"facet.range", field |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start","43" |
| ,"facet.range.end","45" |
| ,"facet.range.gap","1" |
| ,"facet.range.other",FacetRangeOther.NONE.toString() |
| ) |
| ,"*[count(//lst[@name='facet_ranges']/lst)=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts']/int)=2]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='after'])=0]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='before'])=0]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='between'])=0]" |
| ); |
| |
| // these should have equivalent behavior (multivalued 'other' param: top level vs local) |
| for (SolrQueryRequest req : new SolrQueryRequest[] { |
| req("q", "id_i1:[42 TO 47]" |
| ,"facet","true" |
| ,"fl","id," + field |
| ,"facet.range", field |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start","43" |
| ,"facet.range.end","45" |
| ,"facet.range.gap","1" |
| ,"facet.range.other",FacetRangeOther.BEFORE.toString() |
| ,"facet.range.other",FacetRangeOther.AFTER.toString()), |
| req("q", "id_i1:[42 TO 47]" |
| ,"facet","true" |
| ,"fl","id," + field |
| ,"facet.range", "{!facet.range.other=before facet.range.other=after}" + field |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start","43" |
| ,"facet.range.end","45" |
| ,"facet.range.gap","1") }) { |
| |
| assertQ("Test facet.range.other: " + req.toString(), req |
| ,"*[count(//lst[@name='facet_ranges']/lst)=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts']/int)=2]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='between'])=0]" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='after'][.='3']" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='before'][.='1']" |
| ); |
| } |
| |
| assertQ("Test facet.range.other", |
| req("q", "id_i1:[42 TO 47]" |
| ,"facet","true" |
| ,"fl","id," + field |
| ,"facet.range", field |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start","43" |
| ,"facet.range.end","45" |
| ,"facet.range.gap","1" |
| ,"facet.range.other",FacetRangeOther.BEFORE.toString() |
| ,"facet.range.other",FacetRangeOther.AFTER.toString() |
| ,"facet.range.other",FacetRangeOther.NONE.toString() |
| ) |
| ,"*[count(//lst[@name='facet_ranges']/lst)=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts']/int)=2]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='between'])=0]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='after'])=0]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='before'])=0]" |
| ); |
| |
| assertQ("Test facet.range.other", |
| req("q", "id_i1:[42 TO 47]" |
| ,"facet","true" |
| ,"fl","id," + field |
| ,"facet.range", field |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start","43" |
| ,"facet.range.end","45" |
| ,"facet.range.gap","1" |
| ,"facet.range.other",FacetRangeOther.ALL.toString() |
| ,"facet.range.include", FacetRangeInclude.LOWER.toString() |
| ) |
| ,"*[count(//lst[@name='facet_ranges']/lst)=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts']/int)=2]" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='between'][.='2']" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='after'][.='3']" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='before'][.='1']" |
| ); |
| |
| assertQ("Test facet.range.other", |
| req("q", "id_i1:[42 TO 47]" |
| ,"facet","true" |
| ,"fl","id," + field |
| ,"facet.range", field |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start","43" |
| ,"facet.range.end","45" |
| ,"facet.range.gap","1" |
| ,"facet.range.other",FacetRangeOther.ALL.toString() |
| ,"facet.range.include", FacetRangeInclude.UPPER.toString() |
| ) |
| ,"*[count(//lst[@name='facet_ranges']/lst)=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts']/int)=2]" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='between'][.='2']" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='after'][.='2']" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='before'][.='2']" |
| ); |
| |
| assertQ("Test facet.range.other", |
| req("q", "id_i1:[42 TO 47]" |
| ,"facet","true" |
| ,"fl","id," + field |
| ,"facet.range", field |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start","43" |
| ,"facet.range.end","45" |
| ,"facet.range.gap","1" |
| ,"facet.range.other",FacetRangeOther.ALL.toString() |
| ,"facet.range.include", FacetRangeInclude.EDGE.toString() |
| ) |
| ,"*[count(//lst[@name='facet_ranges']/lst)=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts']/int)=2]" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='between'][.='3']" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='after'][.='2']" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='before'][.='1']" |
| ); |
| |
| assertQ("Test facet.range.other", |
| req("q", "id_i1:[42 TO 47]" |
| ,"facet","true" |
| ,"fl","id," + field |
| ,"facet.range", field |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start","43" |
| ,"facet.range.end","45" |
| ,"facet.range.gap","1" |
| ,"facet.range.other", FacetRangeOther.ALL.toString() |
| ,"facet.range.include", FacetRangeInclude.OUTER.toString() |
| ) |
| ,"*[count(//lst[@name='facet_ranges']/lst)=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts']/int)=2]" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='between'][.='1']" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='after'][.='3']" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='before'][.='2']" |
| ); |
| |
| assertQ("Test facet.range.other", |
| req("q", "id_i1:[12345 TO 12345]" |
| ,"facet","true" |
| ,"fl","id," + field |
| ,"facet.range", field |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start","43" |
| ,"facet.range.end","45" |
| ,"facet.range.gap","1" |
| ,"facet.range.other", FacetRangeOther.ALL.toString() |
| ) |
| ,"*[count(//lst[@name='facet_ranges']/lst)=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts'])=1]" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='between'][.='0']" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='after'][.='0']" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='before'][.='0']" |
| ); |
| |
| assertQ("Test facet.range.other", |
| req("q", "id_i1:[42 TO 47]" |
| ,"facet","true" |
| ,"fl","id," + field |
| ,"facet.range", field |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start","43" |
| ,"facet.range.end","45" |
| ,"facet.range.gap","10" |
| ,"facet.range.other", FacetRangeOther.ALL.toString() |
| ) |
| ,"*[count(//lst[@name='facet_ranges']/lst)=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts'])=1]" |
| ,"*[count(//lst[@name='facet_ranges']/lst[@name='" + field + "']/lst[@name='counts']/int)=1]" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='between'][.='5']" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='after'][.='0']" |
| ,"//lst[@name='facet_ranges']/lst[@name='" + field + "']/int[@name='before'][.='1']" |
| ); |
| |
| } |
| |
| public void testGroupFacetErrors() { |
| ModifiableSolrParams params = params("q", "*:*", "group", "true", "group.query", "myfield_s:*", |
| "facet", "true", "group.facet", "true"); |
| |
| // with facet.field |
| SolrException ex = expectThrows(SolrException.class, () -> { |
| h.query(req(params, "facet.field", "myfield_s")); |
| }); |
| assertEquals(ErrorCode.BAD_REQUEST.code, ex.code()); |
| assertTrue(ex.getMessage().contains("Specify the group.field as parameter or local parameter")); |
| |
| // with facet.query |
| ex = expectThrows(SolrException.class, () -> { |
| h.query(req(params, "facet.query", "myfield_s:*")); |
| }); |
| assertEquals(ErrorCode.BAD_REQUEST.code, ex.code()); |
| assertTrue(ex.getMessage().contains("Specify the group.field as parameter or local parameter")); |
| |
| // with facet.range |
| ex = expectThrows(SolrException.class, () -> h.query(req(params, "facet.range", "range_facet_l", |
| "facet.range.start", "43", "facet.range.end", "450", "facet.range.gap", "10")) |
| ); |
| assertEquals(ErrorCode.BAD_REQUEST.code, ex.code()); |
| assertTrue(ex.getMessage().contains("Specify the group.field as parameter or local parameter")); |
| |
| // with facet.interval |
| ex = expectThrows(SolrException.class, () -> h.query(req(params, "facet.interval", "range_facet_l", |
| "f.range_facet_l.facet.interval.set", "(43,60]")) |
| ); |
| assertEquals(ErrorCode.BAD_REQUEST.code, ex.code()); |
| assertTrue(ex.getMessage().contains("Interval Faceting can't be used with group.facet")); |
| } |
| |
| public void testRangeFacetingBadRequest() { |
| String field = "range_facet_l"; |
| ignoreException("."); |
| try { |
| for (FacetRangeMethod method:FacetRangeMethod.values()) { |
| assertQEx("Test facet.range bad requests", |
| "range facet 'end' comes before 'start'", |
| req("q", "*:*" |
| ,"facet","true" |
| ,"facet.range", field |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start","45" |
| ,"facet.range.end","43" |
| ,"facet.range.gap","10" |
| ), |
| ErrorCode.BAD_REQUEST |
| ); |
| |
| assertQEx("Test facet.range bad requests", |
| "range facet infinite loop (is gap negative? did the math overflow?)", |
| req("q", "*:*" |
| ,"facet","true" |
| ,"facet.range", field |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start","43" |
| ,"facet.range.end","45" |
| ,"facet.range.gap","-1" |
| ), |
| ErrorCode.BAD_REQUEST |
| ); |
| |
| assertQEx("Test facet.range bad requests", |
| "range facet infinite loop: gap is either zero, or too small relative start/end and caused underflow", |
| req("q", "*:*" |
| ,"facet","true" |
| ,"facet.range", field |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start","43" |
| ,"facet.range.end","45" |
| ,"facet.range.gap","0" |
| ), |
| ErrorCode.BAD_REQUEST |
| ); |
| |
| assertQEx("Test facet.range bad requests", |
| "Missing required parameter", |
| req("q", "*:*" |
| ,"facet","true" |
| ,"facet.range", field |
| ,"facet.range.method", method.toString() |
| ,"facet.range.end","45" |
| ,"facet.range.gap","5" |
| ), |
| ErrorCode.BAD_REQUEST |
| ); |
| assertQEx("Test facet.range bad requests", |
| "Missing required parameter", |
| req("q", "*:*" |
| ,"facet","true" |
| ,"facet.range", field |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start","43" |
| ,"facet.range.gap","5" |
| ), |
| ErrorCode.BAD_REQUEST |
| ); |
| assertQEx("Test facet.range bad requests", |
| "Missing required parameter", |
| req("q", "*:*" |
| ,"facet","true" |
| ,"facet.range", field |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start","43" |
| ,"facet.range.end","45" |
| ), |
| ErrorCode.BAD_REQUEST |
| ); |
| assertQEx("Test facet.range bad requests", |
| "Unable to range facet on field", |
| req("q", "*:*" |
| ,"facet","true" |
| ,"facet.range", "contains_s1" |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start","43" |
| ,"facet.range.end","45" |
| ,"facet.range.gap","5" |
| ), |
| ErrorCode.BAD_REQUEST |
| ); |
| assertQEx("Test facet.range bad requests", |
| "foo is not a valid method for range faceting", |
| req("q", "*:*" |
| ,"facet","true" |
| ,"facet.range", field |
| ,"facet.range.method", "foo" |
| ,"facet.range.start","43" |
| ,"facet.range.end","45" |
| ,"facet.range.gap","5" |
| ), |
| ErrorCode.BAD_REQUEST |
| ); |
| |
| assertQEx("Test facet.range bad requests", |
| "foo is not a valid type of for range 'include' information", |
| req("q", "*:*" |
| ,"facet","true" |
| ,"facet.range", field |
| ,"facet.range.method", method.toString() |
| ,"facet.range.start","43" |
| ,"facet.range.end","45" |
| ,"facet.range.gap","5" |
| ,"facet.range.include", "foo" |
| ), |
| ErrorCode.BAD_REQUEST |
| ); |
| } |
| } finally { |
| resetExceptionIgnores(); |
| } |
| |
| } |
| |
| @SuppressWarnings("unchecked") |
| public void testRangeFacetFilterVsDocValuesRandom() throws Exception { |
| for (int i = 0; i < atLeast(100); i++) { |
| ModifiableSolrParams params = null; |
| int fieldType = i%3; |
| switch (fieldType) { |
| case 0: params = getRandomParamsDate(); break; |
| case 1: params = getRandomParamsInt(); break; |
| case 2: params = getRandomParamsFloat(); break; |
| } |
| String field = params.get("facet.range"); |
| params.add("q", getRandomQuery()); |
| |
| |
| params.add("facet", "true"); |
| if (random().nextBoolean()) { |
| params.add("facet.range.method", FacetRangeMethod.FILTER.toString()); |
| } |
| |
| NamedList<Object> rangeFacetsFilter; |
| NamedList<Object> rangeFacetsDv; |
| |
| SolrQueryRequest req = req(params); |
| log.info("Using Params: {}", params); |
| try { |
| SolrQueryResponse rsp = h.queryAndResponse("", req); |
| rangeFacetsFilter = (NamedList<Object>) ((NamedList<Object>) rsp.getValues().get("facet_counts")).get("facet_ranges"); |
| } finally { |
| req.close(); |
| } |
| params.add("facet.range.method", FacetRangeMethod.DV.toString()); |
| req = req(params); |
| try { |
| SolrQueryResponse rsp = h.queryAndResponse("", req); |
| rangeFacetsDv = (NamedList<Object>) ((NamedList<Object>) rsp.getValues().get("facet_counts")).get("facet_ranges"); |
| } finally { |
| req.close(); |
| } |
| |
| assertNotNull(rangeFacetsFilter.get(field)); |
| assertNotNull(rangeFacetsDv.get(field)); |
| |
| assertSameResults("Different results obtained when using 'filter' and 'dv' methods for Range Facets using params." |
| + params + "\n" + "Filter:" + rangeFacetsFilter + "\n DV: " + rangeFacetsDv, |
| (NamedList<Object>)rangeFacetsFilter.get(field), (NamedList<Object>)rangeFacetsDv.get(field)); |
| } |
| |
| } |
| |
| public void testFacetPrefixWithFacetThreads() throws Exception { |
| assertQ("Test facet.prefix with facet.thread", |
| req("q", "id_i1:[101 TO 102]" |
| ,"facet","true" |
| ,"facet.field", "{!key=key1 facet.prefix=foo}myfield_s" |
| ,"facet.field", "{!key=key2 facet.prefix=bar}myfield_s" |
| ,"facet.threads", "1" |
| ) |
| ,"*[count(//lst[@name='facet_fields']/lst[@name='key1']/int[@name='foo'])=1]" |
| ,"*[count(//lst[@name='facet_fields']/lst[@name='key2']/int[@name='bar'])=1]" |
| ); |
| |
| } |
| |
| private String getRandomQuery() { |
| if (rarely()) { |
| return "*:*"; |
| } |
| Integer[] values = new Integer[2]; |
| values[0] = random().nextInt(3000); |
| values[1] = random().nextInt(3000); |
| Arrays.sort(values); |
| return String.format(Locale.ROOT, "id_i1:[%d TO %d]", values[0], values[1]); |
| } |
| |
| |
| private void assertSameResults(String message, |
| NamedList<Object> rangeFacetsFilter, NamedList<Object> rangeFacetsDv) { |
| assertEquals(message + " Different number of elements.", rangeFacetsFilter.size(), rangeFacetsDv.size()); |
| for (Map.Entry<String, Object> entry:rangeFacetsFilter) { |
| if (entry.getKey().equals("counts")) { |
| continue; |
| } |
| Object value = rangeFacetsDv.get(entry.getKey()); |
| if (value == null) { |
| fail(message + " Element not found with 'dv' method: " + entry.getKey()); |
| } |
| assertEquals(message + "Different value for key " + entry.getKey(), entry.getValue(), value); |
| } |
| assertNotNull("Null counts: " + rangeFacetsFilter, rangeFacetsFilter.get("counts")); |
| assertNotNull("Null counts: " + rangeFacetsDv, rangeFacetsDv.get("counts")); |
| assertEquals(message + "Different counts", rangeFacetsFilter.get("counts"), rangeFacetsDv.get("counts")); |
| } |
| |
| private ModifiableSolrParams getRandomParamsInt() { |
| String field = new String[]{"range_facet_l_dv", "range_facet_i_dv", "range_facet_l", "duration_i1", "id_i1"}[random().nextInt(5)]; |
| ModifiableSolrParams params = new ModifiableSolrParams(); |
| Integer[] values = new Integer[2]; |
| do { |
| values[0] = random().nextInt(3000) * (random().nextBoolean()?-1:1); |
| values[1] = random().nextInt(3000) * (random().nextBoolean()?-1:1); |
| } while (values[0].equals(values[1])); |
| Arrays.sort(values); |
| long gapNum = Math.max(1, random().nextInt(3000)); |
| |
| params.add(FacetParams.FACET_RANGE_START, String.valueOf(values[0])); |
| params.add(FacetParams.FACET_RANGE_END, String.valueOf(values[1])); |
| params.add(FacetParams.FACET_RANGE_GAP, String.format(Locale.ROOT, "+%d", gapNum)); |
| addCommonRandomRangeParams(params); |
| params.add(FacetParams.FACET_RANGE, field); |
| return params; |
| } |
| |
| private ModifiableSolrParams getRandomParamsFloat() { |
| String field = new String[]{"range_facet_d_dv", "range_facet_f_dv", "range_facet_d", "range_facet_f", "range_facet_mv_f", "range_facet_f1", "range_facet_f1_dv"}[random().nextInt(7)]; |
| ModifiableSolrParams params = new ModifiableSolrParams(); |
| Float[] values = new Float[2]; |
| do { |
| values[0] = random().nextFloat() * 3000 * (random().nextBoolean()?-1:1); |
| values[1] = random().nextFloat() * 3000 * (random().nextBoolean()?-1:1); |
| } while (values[0].equals(values[1])); |
| Arrays.sort(values); |
| float gapNum = Math.max(1, random().nextFloat() * 3000); |
| |
| params.add(FacetParams.FACET_RANGE_START, String.valueOf(values[0])); |
| params.add(FacetParams.FACET_RANGE_END, String.valueOf(values[1])); |
| params.add(FacetParams.FACET_RANGE_GAP, String.format(Locale.ROOT, "+%f", gapNum)); |
| addCommonRandomRangeParams(params); |
| params.add(FacetParams.FACET_RANGE, field); |
| return params; |
| } |
| |
| private final static String[] DATE_GAP_UNITS = new String[]{"SECONDS", "MINUTES", "HOURS", "DAYS", "MONTHS", "YEARS"}; |
| |
| private ModifiableSolrParams getRandomParamsDate() { |
| String field = new String[]{"range_facet_dt_dv", "a_tdt", "bday"}[random().nextInt(3)]; |
| ModifiableSolrParams params = new ModifiableSolrParams(); |
| Date[] dates = new Date[2]; |
| do { |
| dates[0] = new Date((long)(random().nextDouble()*(new Date().getTime()) * (random().nextBoolean()?-1:1))); |
| dates[1] = new Date((long)(random().nextDouble()*(new Date().getTime()) * (random().nextBoolean()?-1:1))); |
| } while (dates[0].equals(dates[1])); |
| Arrays.sort(dates); |
| long dateDiff = (dates[1].getTime() - dates[0].getTime())/1000; |
| String gapUnit; |
| if (dateDiff < 1000) { |
| gapUnit = DATE_GAP_UNITS[random().nextInt(DATE_GAP_UNITS.length)]; |
| } else if (dateDiff < 10000){ |
| gapUnit = DATE_GAP_UNITS[1 + random().nextInt(DATE_GAP_UNITS.length - 1)]; |
| } else if (dateDiff < 100000){ |
| gapUnit = DATE_GAP_UNITS[2 + random().nextInt(DATE_GAP_UNITS.length - 2)]; |
| } else if (dateDiff < 1000000){ |
| gapUnit = DATE_GAP_UNITS[3 + random().nextInt(DATE_GAP_UNITS.length - 3)]; |
| } else { |
| gapUnit = DATE_GAP_UNITS[4 + random().nextInt(DATE_GAP_UNITS.length - 4)]; |
| } |
| int gapNum = random().nextInt(100) + 1; |
| |
| params.add(FacetParams.FACET_RANGE_START, dates[0].toInstant().toString()); |
| params.add(FacetParams.FACET_RANGE_END, dates[1].toInstant().toString()); |
| params.add(FacetParams.FACET_RANGE_GAP, String.format(Locale.ROOT, "+%d%s", gapNum, gapUnit)); |
| addCommonRandomRangeParams(params); |
| params.add(FacetParams.FACET_RANGE, field); |
| return params; |
| } |
| |
| |
| private void addCommonRandomRangeParams(ModifiableSolrParams params) { |
| for (int i = 0; i < random().nextInt(2); i++) { |
| params.add(FacetParams.FACET_RANGE_OTHER, FacetRangeOther.values()[random().nextInt(FacetRangeOther.values().length)].toString()); |
| } |
| if (random().nextBoolean()) { |
| params.add(FacetParams.FACET_RANGE_INCLUDE, FacetRangeInclude.values()[random().nextInt(FacetRangeInclude.values().length)].toString()); |
| } |
| if (random().nextBoolean()) { |
| params.add(FacetParams.FACET_MINCOUNT, String.valueOf(random().nextInt(10))); |
| } |
| params.add(FacetParams.FACET_RANGE_HARD_END, String.valueOf(random().nextBoolean())); |
| } |
| |
| } |