| /* |
| * 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.handler.component; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.Date; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import junit.framework.AssertionFailedError; |
| import org.apache.solr.BaseDistributedSearchTestCase; |
| import org.apache.solr.client.solrj.response.FieldStatsInfo; |
| import org.apache.solr.client.solrj.response.PivotField; |
| import org.apache.solr.client.solrj.response.QueryResponse; |
| import org.apache.solr.client.solrj.response.RangeFacet; |
| import org.apache.solr.common.params.FacetParams; |
| import org.apache.solr.common.params.ModifiableSolrParams; |
| import org.apache.solr.common.params.SolrParams; |
| import org.junit.Test; |
| |
| public class DistributedFacetPivotSmallTest extends BaseDistributedSearchTestCase { |
| |
| public DistributedFacetPivotSmallTest() { |
| // we need DVs on point fields to compute stats & facets |
| if (Boolean.getBoolean(NUMERIC_POINTS_SYSPROP)) System.setProperty(NUMERIC_DOCVALUES_SYSPROP,"true"); |
| } |
| |
| @Test |
| @ShardsFixed(num = 4) |
| public void test() throws Exception { |
| |
| del("*:*"); |
| |
| // NOTE: we use the literal (4 character) string "null" as a company name |
| // to help ensure there isn't any bugs where the literal string is treated as if it |
| // were a true NULL value. |
| index(id, 19, "place_t", "cardiff dublin", "company_t", "microsoft polecat", "price_ti", "15"); |
| index(id, 20, "place_t", "dublin", "company_t", "polecat microsoft null", "price_ti", "19", |
| // this is the only doc to have solo_* fields, therefore only 1 shard has them |
| // TODO: add enum field - blocked by SOLR-6682 |
| "solo_i", 42, "solo_s", "lonely", "solo_dt", "1976-03-06T01:23:45Z"); |
| index(id, 21, "place_t", "london la dublin", "company_t", |
| "microsoft fujitsu null polecat", "price_ti", "29"); |
| index(id, 22, "place_t", "krakow london cardiff", "company_t", |
| "polecat null bbc", "price_ti", "39"); |
| index(id, 23, "place_t", "london", "company_t", "", "price_ti", "29"); |
| index(id, 24, "place_t", "la", "company_t", ""); |
| index(id, 25, "company_t", "microsoft polecat null fujitsu null bbc", "price_ti", "59"); |
| index(id, 26, "place_t", "krakow", "company_t", "null"); |
| index(id, 27, "place_t", "krakow cardiff dublin london la", |
| "company_t", "null microsoft polecat bbc fujitsu"); |
| index(id, 28, "place_t", "cork", "company_t", "fujitsu rte"); |
| commit(); |
| |
| handle.clear(); |
| handle.put("QTime", SKIPVAL); |
| handle.put("timestamp", SKIPVAL); |
| handle.put("maxScore", SKIPVAL); |
| |
| |
| final ModifiableSolrParams params = new ModifiableSolrParams(); |
| setDistributedParams(params); |
| params.add("q", "*:*"); |
| params.add("facet", "true"); |
| params.add("facet.pivot", "place_t,company_t"); |
| |
| |
| QueryResponse rsp = queryServer(params); |
| |
| List<PivotField> expectedPlacePivots = new UnorderedEqualityArrayList<PivotField>(); |
| List<PivotField> expectedCardiffPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedCardiffPivots.add(new ComparablePivotField("company_t", "microsoft", 2, null)); |
| expectedCardiffPivots.add(new ComparablePivotField("company_t", "null", 2, null)); |
| expectedCardiffPivots.add(new ComparablePivotField("company_t", "bbc", 2, null)); |
| expectedCardiffPivots.add(new ComparablePivotField("company_t", "polecat", 3, null)); |
| expectedCardiffPivots.add(new ComparablePivotField("company_t", "fujitsu", 1, null)); |
| List<PivotField> expectedDublinPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "polecat", 4, null)); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "microsoft", 4, null)); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "null", 3, null)); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "fujitsu", 2, null)); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "bbc", 1, null)); |
| List<PivotField> expectedLondonPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "polecat", 3, null)); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "microsoft", 2, null)); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "fujitsu", 2, null)); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "null", 3,null)); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "bbc", 2, null)); |
| List<PivotField> expectedLAPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedLAPivots.add(new ComparablePivotField("company_t", "microsoft", 2,null)); |
| expectedLAPivots.add(new ComparablePivotField("company_t", "fujitsu", 2,null)); |
| expectedLAPivots.add(new ComparablePivotField("company_t", "null", 2, null)); |
| expectedLAPivots.add(new ComparablePivotField("company_t", "bbc", 1, null)); |
| expectedLAPivots.add(new ComparablePivotField("company_t", "polecat", 2,null)); |
| List<PivotField> expectedKrakowPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedKrakowPivots.add(new ComparablePivotField("company_t", "polecat",2, null)); |
| expectedKrakowPivots.add(new ComparablePivotField("company_t", "bbc", 2, null)); |
| expectedKrakowPivots.add(new ComparablePivotField("company_t", "null", 3,null)); |
| expectedKrakowPivots.add(new ComparablePivotField("company_t", "fujitsu", 1, null)); |
| expectedKrakowPivots.add(new ComparablePivotField("company_t", "microsoft", 1, null)); |
| List<PivotField> expectedCorkPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedCorkPivots.add(new ComparablePivotField("company_t", "fujitsu", 1, null)); |
| expectedCorkPivots.add(new ComparablePivotField("company_t", "rte", 1, null)); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "dublin", 4, expectedDublinPivots)); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "cardiff", 3, expectedCardiffPivots)); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "london", 4, expectedLondonPivots)); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "la", 3, expectedLAPivots)); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "krakow", 3, expectedKrakowPivots)); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "cork", 1, expectedCorkPivots)); |
| |
| |
| List<PivotField> placePivots = rsp.getFacetPivot().get("place_t,company_t"); |
| |
| // Useful to check for errors, orders lists and does toString() equality |
| // check |
| testOrderedPivotsStringEquality(expectedPlacePivots, placePivots); |
| |
| assertEquals(expectedPlacePivots, placePivots); |
| |
| // Test sorting by count |
| |
| params.set(FacetParams.FACET_SORT, FacetParams.FACET_SORT_COUNT); |
| |
| rsp = queryServer(params); |
| |
| placePivots = rsp.getFacetPivot().get("place_t,company_t"); |
| |
| testCountSorting(placePivots); |
| |
| // Test limit |
| |
| params.set(FacetParams.FACET_LIMIT, 2); |
| |
| rsp = queryServer(params); |
| |
| expectedPlacePivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedDublinPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "polecat", |
| 4, null)); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "microsoft", |
| 4, null)); |
| expectedLondonPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "null", 3, |
| null)); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "polecat", 3, |
| null)); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "dublin", 4, |
| expectedDublinPivots)); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "london", 4, |
| expectedLondonPivots)); |
| |
| placePivots = rsp.getFacetPivot().get("place_t,company_t"); |
| |
| assertEquals(expectedPlacePivots, placePivots); |
| |
| // Test individual facet.limit values |
| params.remove(FacetParams.FACET_LIMIT); |
| |
| params.set("f.place_t." + FacetParams.FACET_LIMIT, 1); |
| params.set("f.company_t." + FacetParams.FACET_LIMIT, 4); |
| |
| rsp = queryServer(params); |
| |
| expectedPlacePivots = new UnorderedEqualityArrayList<PivotField>(); |
| |
| expectedDublinPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "microsoft",4, null)); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "polecat",4, null)); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "null",3, null)); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "fujitsu",2, null)); |
| |
| expectedLondonPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "null", 3, null)); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "polecat", 3, null)); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "bbc", 2, null)); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "fujitsu", 2, null)); |
| |
| expectedCardiffPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedCardiffPivots.add(new ComparablePivotField("company_t", "polecat", 3, null)); |
| |
| expectedKrakowPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedKrakowPivots.add(new ComparablePivotField("company_t", "null", 3, null)); |
| |
| expectedLAPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedLAPivots.add(new ComparablePivotField("company_t", "fujitsu", 2, null)); |
| |
| expectedCorkPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedCorkPivots.add(new ComparablePivotField("company_t", "fujitsu", 1, null)); |
| |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "dublin", 4, expectedDublinPivots)); |
| |
| placePivots = rsp.getFacetPivot().get("place_t,company_t"); |
| assertEquals(expectedPlacePivots, placePivots); |
| |
| params.remove("f.company_t." + FacetParams.FACET_LIMIT); |
| params.remove("f.place_t." + FacetParams.FACET_LIMIT); |
| params.set(FacetParams.FACET_LIMIT, 2); |
| |
| // Test facet.missing=true with diff sorts |
| |
| index("id",777); // NOTE: id=25 has no place as well |
| commit(); |
| |
| SolrParams missingA = params( "q", "*:*", |
| "rows", "0", |
| "facet","true", |
| "facet.pivot","place_t,company_t", |
| "f.place_t.facet.mincount", "2", |
| // default facet.sort |
| FacetParams.FACET_MISSING, "true" ); |
| SolrParams missingB = SolrParams.wrapDefaults(missingA, |
| params(FacetParams.FACET_LIMIT, "4", |
| "facet.sort", "index")); |
| for (SolrParams p : new SolrParams[] { missingA, missingB }) { |
| // in either case, the last pivot option should be the same |
| rsp = query( p ); |
| placePivots = rsp.getFacetPivot().get("place_t,company_t"); |
| assertTrue("not enough values for pivot: " + p + " => " + placePivots, |
| 1 < placePivots.size()); |
| PivotField missing = placePivots.get(placePivots.size()-1); |
| assertNull("not the missing place value: " + p, missing.getValue()); |
| assertEquals("wrong missing place count: " + p, 2, missing.getCount()); |
| assertTrue("not enough sub-pivots for missing place: "+ p +" => " + missing.getPivot(), |
| 1 < missing.getPivot().size()); |
| missing = missing.getPivot().get(missing.getPivot().size()-1); |
| assertNull("not the missing company value: " + p, missing.getValue()); |
| assertEquals("wrong missing company count: " + p, 1, missing.getCount()); |
| assertNull("company shouldn't have sub-pivots: " + p, missing.getPivot()); |
| } |
| |
| // sort=index + mincount + limit |
| for (SolrParams variableParams : new SolrParams[] { |
| // we should get the same results regardless of overrequest |
| params("facet.overrequest.count","0", |
| "facet.overrequest.ratio","0"), |
| params() }) { |
| |
| |
| SolrParams p = SolrParams.wrapDefaults( params( "q", "*:*", |
| "rows", "0", |
| "facet","true", |
| "facet.pivot","company_t", |
| "facet.sort", "index", |
| "facet.pivot.mincount", "4", |
| "facet.limit", "4"), |
| variableParams ); |
| |
| try { |
| List<PivotField> pivots = query( p ).getFacetPivot().get("company_t"); |
| assertEquals(4, pivots.size()); |
| assertEquals("fujitsu", pivots.get(0).getValue()); |
| assertEquals(4, pivots.get(0).getCount()); |
| assertEquals("microsoft", pivots.get(1).getValue()); |
| assertEquals(5, pivots.get(1).getCount()); |
| assertEquals("null", pivots.get(2).getValue()); |
| assertEquals(6, pivots.get(2).getCount()); |
| assertEquals("polecat", pivots.get(3).getValue()); |
| assertEquals(6, pivots.get(3).getCount()); |
| |
| } catch (AssertionFailedError ae) { |
| throw new AssertionError(ae.getMessage() + " <== " + p.toString(), ae); |
| } |
| } |
| |
| // sort=index + mincount + limit + offset |
| for (SolrParams variableParams : new SolrParams[] { |
| // we should get the same results regardless of overrequest |
| params("facet.overrequest.count","0", |
| "facet.overrequest.ratio","0"), |
| params() }) { |
| |
| SolrParams p = SolrParams.wrapDefaults( params( "q", "*:*", |
| "rows", "0", |
| "facet","true", |
| "facet.pivot","company_t", |
| "facet.sort", "index", |
| "facet.pivot.mincount", "4", |
| "facet.offset", "1", |
| "facet.limit", "4"), |
| variableParams ); |
| try { |
| List<PivotField> pivots = query( p ).getFacetPivot().get("company_t"); |
| assertEquals(3, pivots.size()); // asked for 4, but not enough meet the mincount |
| assertEquals("microsoft", pivots.get(0).getValue()); |
| assertEquals(5, pivots.get(0).getCount()); |
| assertEquals("null", pivots.get(1).getValue()); |
| assertEquals(6, pivots.get(1).getCount()); |
| assertEquals("polecat", pivots.get(2).getValue()); |
| assertEquals(6, pivots.get(2).getCount()); |
| |
| } catch (AssertionFailedError ae) { |
| throw new AssertionError(ae.getMessage() + " <== " + p.toString(), ae); |
| } |
| |
| } |
| |
| // sort=index + mincount + limit + offset (more permutations) |
| for (SolrParams variableParams : new SolrParams[] { |
| // all of these combinations should result in the same first value |
| params("facet.pivot.mincount", "4", |
| "facet.offset", "2"), |
| params("facet.pivot.mincount", "5", |
| "facet.offset", "1"), |
| params("facet.pivot.mincount", "6", |
| "facet.offset", "0" ) }) { |
| |
| SolrParams p = SolrParams.wrapDefaults( params( "q", "*:*", |
| "rows", "0", |
| "facet","true", |
| "facet.limit","1", |
| "facet.sort","index", |
| "facet.overrequest.ratio","0", |
| "facet.pivot", "company_t"), |
| variableParams ); |
| |
| try { |
| List<PivotField> pivots = query( p ).getFacetPivot().get("company_t"); |
| assertEquals(1, pivots.size()); |
| assertEquals(pivots.toString(), "null", pivots.get(0).getValue()); |
| assertEquals(pivots.toString(), 6, pivots.get(0).getCount()); |
| |
| } catch (AssertionFailedError ae) { |
| throw new AssertionError(ae.getMessage() + " <== " + p.toString(), ae); |
| } |
| } |
| |
| doTestDeepPivotStats(false); // all price stats |
| doTestDeepPivotStats(true); // just the mean price stat |
| |
| doTestPivotStatsFromOneShard(); |
| |
| testFacetPivotRange(); |
| |
| testFacetPivotQuery(); |
| |
| testNegativeFacetQuery(); |
| |
| testNegativeRangeQuery(); |
| |
| testPivotFacetRangeAndQuery(); |
| } |
| |
| /** |
| * @param justMean - only the mean stat is requested/computed |
| */ |
| private void doTestDeepPivotStats(boolean justMean) throws Exception { |
| SolrParams params = params("q", "*:*", "rows", "0", |
| "facet", "true", "stats", "true", |
| "facet.pivot", "{!stats=s1}place_t,company_t", |
| "stats.field", ("{!key=avg_price tag=s1 "+ |
| (justMean ? "mean=true" : "") +"}price_ti")); |
| QueryResponse rsp = query(params); |
| |
| List<PivotField> placePivots = rsp.getFacetPivot().get("place_t,company_t"); |
| |
| PivotField dublinPivotField = placePivots.get(0); |
| assertEquals("dublin", dublinPivotField.getValue()); |
| assertEquals(4, dublinPivotField.getCount()); |
| |
| PivotField microsoftPivotField = dublinPivotField.getPivot().get(0); |
| assertEquals("microsoft", microsoftPivotField.getValue()); |
| assertEquals(4, microsoftPivotField.getCount()); |
| |
| FieldStatsInfo dublinMicrosoftStatsInfo = microsoftPivotField.getFieldStatsInfo().get("avg_price"); |
| assertEquals(21.0, (double) dublinMicrosoftStatsInfo.getMean(), 0.1E-7); |
| if (justMean) { |
| assertNull(dublinMicrosoftStatsInfo.getMin()); |
| assertNull(dublinMicrosoftStatsInfo.getMax()); |
| assertNull(dublinMicrosoftStatsInfo.getCount()); |
| assertNull(dublinMicrosoftStatsInfo.getMissing()); |
| assertNull(dublinMicrosoftStatsInfo.getSum()); |
| assertNull(dublinMicrosoftStatsInfo.getSumOfSquares()); |
| assertNull(dublinMicrosoftStatsInfo.getStddev()); |
| } else { |
| assertEquals(15.0, dublinMicrosoftStatsInfo.getMin()); |
| assertEquals(29.0, dublinMicrosoftStatsInfo.getMax()); |
| assertEquals(3, (long) dublinMicrosoftStatsInfo.getCount()); |
| assertEquals(1, (long) dublinMicrosoftStatsInfo.getMissing()); |
| assertEquals(63.0, dublinMicrosoftStatsInfo.getSum()); |
| assertEquals(1427.0, dublinMicrosoftStatsInfo.getSumOfSquares(), 0.1E-7); |
| assertEquals(7.211102550927978, dublinMicrosoftStatsInfo.getStddev(), 0.1E-7); |
| } |
| |
| PivotField cardiffPivotField = placePivots.get(2); |
| assertEquals("cardiff", cardiffPivotField.getValue()); |
| assertEquals(3, cardiffPivotField.getCount()); |
| |
| PivotField polecatPivotField = cardiffPivotField.getPivot().get(0); |
| assertEquals("polecat", polecatPivotField.getValue()); |
| assertEquals(3, polecatPivotField.getCount()); |
| |
| FieldStatsInfo cardiffPolecatStatsInfo = polecatPivotField.getFieldStatsInfo().get("avg_price"); |
| assertEquals(27.0, (double) cardiffPolecatStatsInfo.getMean(), 0.1E-7); |
| if (justMean) { |
| assertNull(cardiffPolecatStatsInfo.getMin()); |
| assertNull(cardiffPolecatStatsInfo.getMax()); |
| assertNull(cardiffPolecatStatsInfo.getCount()); |
| assertNull(cardiffPolecatStatsInfo.getMissing()); |
| assertNull(cardiffPolecatStatsInfo.getSum()); |
| assertNull(cardiffPolecatStatsInfo.getSumOfSquares()); |
| assertNull(cardiffPolecatStatsInfo.getStddev()); |
| } else { |
| assertEquals(15.0, cardiffPolecatStatsInfo.getMin()); |
| assertEquals(39.0, cardiffPolecatStatsInfo.getMax()); |
| assertEquals(2, (long) cardiffPolecatStatsInfo.getCount()); |
| assertEquals(1, (long) cardiffPolecatStatsInfo.getMissing()); |
| assertEquals(54.0, cardiffPolecatStatsInfo.getSum()); |
| assertEquals(1746.0, cardiffPolecatStatsInfo.getSumOfSquares(), 0.1E-7); |
| assertEquals(16.97056274847714, cardiffPolecatStatsInfo.getStddev(), 0.1E-7); |
| } |
| |
| PivotField krakowPivotField = placePivots.get(3); |
| assertEquals("krakow", krakowPivotField.getValue()); |
| assertEquals(3, krakowPivotField.getCount()); |
| |
| PivotField fujitsuPivotField = krakowPivotField.getPivot().get(3); |
| assertEquals("fujitsu", fujitsuPivotField.getValue()); |
| assertEquals(1, fujitsuPivotField.getCount()); |
| |
| FieldStatsInfo krakowFujitsuStatsInfo = fujitsuPivotField.getFieldStatsInfo().get("avg_price"); |
| assertEquals(Double.NaN, (double) krakowFujitsuStatsInfo.getMean(), 0.1E-7); |
| if (justMean) { |
| assertNull(krakowFujitsuStatsInfo.getMin()); |
| assertNull(krakowFujitsuStatsInfo.getMax()); |
| assertNull(krakowFujitsuStatsInfo.getCount()); |
| assertNull(krakowFujitsuStatsInfo.getMissing()); |
| assertNull(krakowFujitsuStatsInfo.getSum()); |
| assertNull(krakowFujitsuStatsInfo.getSumOfSquares()); |
| assertNull(krakowFujitsuStatsInfo.getStddev()); |
| } else { |
| assertEquals(null, krakowFujitsuStatsInfo.getMin()); |
| assertEquals(null, krakowFujitsuStatsInfo.getMax()); |
| assertEquals(0, (long) krakowFujitsuStatsInfo.getCount()); |
| assertEquals(1, (long) krakowFujitsuStatsInfo.getMissing()); |
| assertEquals(0.0, krakowFujitsuStatsInfo.getSum()); |
| assertEquals(0.0, krakowFujitsuStatsInfo.getSumOfSquares(), 0.1E-7); |
| assertEquals(Double.NaN, (double) krakowFujitsuStatsInfo.getMean(), 0.1E-7); |
| assertEquals(0.0, krakowFujitsuStatsInfo.getStddev(), 0.1E-7); |
| } |
| } |
| |
| private void testFacetPivotRange() throws Exception { |
| final ModifiableSolrParams params = new ModifiableSolrParams(); |
| setDistributedParams(params); |
| params.add("q", "*:*"); |
| params.add("facet", "true"); |
| params.add("facet.pivot", "{!range=s1}place_t,company_t"); |
| params.add("facet.range", "{!tag=s1 key=price}price_ti"); |
| params.add("facet.range.start", "0"); |
| params.add("facet.range.end", "100"); |
| params.add("facet.range.gap", "20"); |
| |
| QueryResponse rsp = queryServer(params); |
| |
| List<PivotField> expectedPlacePivots = new UnorderedEqualityArrayList<PivotField>(); |
| List<PivotField> expectedCardiffPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedCardiffPivots.add(new ComparablePivotField("company_t", |
| "microsoft", 2, null, null, createExpectedRange("price", 0, 100, |
| 20, 1, 0, 0, 0, 0))); |
| expectedCardiffPivots.add(new ComparablePivotField("company_t", "null", 2, |
| null, null, createExpectedRange("price", 0, 100, 20, 0, 1, 0, 0, |
| 0))); |
| expectedCardiffPivots.add(new ComparablePivotField("company_t", "bbc", 2, |
| null, null, createExpectedRange("price", 0, 100, 20, 0, 1, 0, 0, |
| 0))); |
| expectedCardiffPivots.add(new ComparablePivotField("company_t", "polecat", |
| 3, null, null, createExpectedRange("price", 0, 100, 20, 1, 1, 0, |
| 0, 0))); |
| expectedCardiffPivots.add(new ComparablePivotField("company_t", "fujitsu", |
| 1, null, null, createExpectedRange("price", 0, 100, 20, 0, 0, 0, |
| 0, 0))); |
| List<PivotField> expectedDublinPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "polecat", |
| 4, null, null, createExpectedRange("price", 0, 100, 20, 2, 1, 0, |
| 0, 0))); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "microsoft", |
| 4, null, null, createExpectedRange("price", 0, 100, 20, 2, 1, 0, |
| 0, 0))); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "null", 3, |
| null, null, createExpectedRange("price", 0, 100, 20, 1, 1, 0, 0, |
| 0))); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "fujitsu", |
| 2, null, null, createExpectedRange("price", 0, 100, 20, 0, 1, 0, |
| 0, 0))); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "bbc", 1, |
| null, null, createExpectedRange("price", 0, 100, 20, 0, 0, 0, 0, |
| 0))); |
| List<PivotField> expectedLondonPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "polecat", |
| 3, null, null, createExpectedRange("price", 0, 100, 20, 0, 2, 0, |
| 0, 0))); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "microsoft", |
| 2, null, null, createExpectedRange("price", 0, 100, 20, 0, 1, 0, |
| 0, 0))); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "fujitsu", |
| 2, null, null, createExpectedRange("price", 0, 100, 20, 0, 1, 0, |
| 0, 0))); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "null", 3, |
| null, null, createExpectedRange("price", 0, 100, 20, 0, 2, 0, 0, |
| 0))); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "bbc", 2, |
| null, null, createExpectedRange("price", 0, 100, 20, 0, 1, 0, 0, |
| 0))); |
| List<PivotField> expectedLAPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedLAPivots.add(new ComparablePivotField("company_t", "microsoft", 2, |
| null, null, createExpectedRange("price", 0, 100, 20, 0, 1, 0, 0, |
| 0))); |
| expectedLAPivots.add(new ComparablePivotField("company_t", "fujitsu", 2, |
| null, null, createExpectedRange("price", 0, 100, 20, 0, 1, 0, 0, |
| 0))); |
| expectedLAPivots.add(new ComparablePivotField("company_t", "null", 2, null, |
| null, createExpectedRange("price", 0, 100, 20, 0, 1, 0, 0, 0))); |
| expectedLAPivots.add(new ComparablePivotField("company_t", "bbc", 1, null, |
| null, createExpectedRange("price", 0, 100, 20, 0, 0, 0, 0, 0))); |
| expectedLAPivots.add(new ComparablePivotField("company_t", "polecat", 2, |
| null, null, createExpectedRange("price", 0, 100, 20, 0, 1, 0, 0, |
| 0))); |
| List<PivotField> expectedKrakowPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedKrakowPivots.add(new ComparablePivotField("company_t", "polecat", |
| 2, null, null, createExpectedRange("price", 0, 100, 20, 0, 1, 0, |
| 0, 0))); |
| expectedKrakowPivots.add(new ComparablePivotField("company_t", "bbc", 2, |
| null, null, createExpectedRange("price", 0, 100, 20, 0, 1, 0, 0, |
| 0))); |
| expectedKrakowPivots.add(new ComparablePivotField("company_t", "null", 3, |
| null, null, createExpectedRange("price", 0, 100, 20, 0, 1, 0, 0, |
| 0))); |
| expectedKrakowPivots.add(new ComparablePivotField("company_t", "fujitsu", |
| 1, null, null, createExpectedRange("price", 0, 100, 20, 0, 0, 0, |
| 0, 0))); |
| expectedKrakowPivots.add(new ComparablePivotField("company_t", "microsoft", |
| 1, null, null, createExpectedRange("price", 0, 100, 20, 0, 0, 0, |
| 0, 0))); |
| List<PivotField> expectedCorkPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedCorkPivots.add(new ComparablePivotField("company_t", "fujitsu", 1, |
| null, null, createExpectedRange("price", 0, 100, 20, 0, 0, 0, 0, |
| 0))); |
| expectedCorkPivots.add(new ComparablePivotField("company_t", "rte", 1, |
| null, null, createExpectedRange("price", 0, 100, 20, 0, 0, 0, 0, |
| 0))); |
| |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "dublin", 4, |
| expectedDublinPivots, null, createExpectedRange("price", 0, 100, |
| 20, 2, 1, 0, 0, 0))); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "cardiff", 3, |
| expectedCardiffPivots, null, createExpectedRange("price", 0, 100, |
| 20, 1, 1, 0, 0, 0))); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "london", 4, |
| expectedLondonPivots, null, createExpectedRange("price", 0, 100, |
| 20, 0, 3, 0, 0, 0))); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "la", 3, |
| expectedLAPivots, null, createExpectedRange("price", 0, 100, 20, |
| 0, 1, 0, 0, 0))); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "krakow", 3, |
| expectedKrakowPivots, null, createExpectedRange("price", 0, 100, |
| 20, 0, 1, 0, 0, 0))); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "cork", 1, |
| expectedCorkPivots, null, createExpectedRange("price", 0, 100, |
| 20, 0, 0, 0, 0, 0))); |
| |
| List<PivotField> placePivots = rsp.getFacetPivot().get("place_t,company_t"); |
| |
| // Useful to check for errors, orders lists and does toString() equality |
| // check |
| testOrderedPivotsStringEquality(expectedPlacePivots, placePivots); |
| |
| assertEquals(expectedPlacePivots, placePivots); |
| |
| // Test sorting by count |
| |
| params.set(FacetParams.FACET_SORT, FacetParams.FACET_SORT_COUNT); |
| |
| rsp = queryServer(params); |
| |
| placePivots = rsp.getFacetPivot().get("place_t,company_t"); |
| |
| testCountSorting(placePivots); |
| |
| // Test limit |
| |
| params.set(FacetParams.FACET_LIMIT, 2); |
| |
| rsp = queryServer(params); |
| |
| expectedPlacePivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedDublinPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "polecat", |
| 4, null, null, createExpectedRange("price", 0, 100, 20, 2, 1, 0, |
| 0, 0))); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "microsoft", |
| 4, null, null, createExpectedRange("price", 0, 100, 20, 2, 1, 0, |
| 0, 0))); |
| expectedLondonPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "null", 3, |
| null, null, createExpectedRange("price", 0, 100, 20, 0, 2, 0, 0, |
| 0))); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "polecat", |
| 3, null, null, createExpectedRange("price", 0, 100, 20, 0, 2, 0, |
| 0, 0))); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "dublin", 4, |
| expectedDublinPivots, null, createExpectedRange("price", 0, 100, |
| 20, 2, 1, 0, 0, 0))); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "london", 4, |
| expectedLondonPivots, null, createExpectedRange("price", 0, 100, |
| 20, 0, 3, 0, 0, 0))); |
| |
| placePivots = rsp.getFacetPivot().get("place_t,company_t"); |
| |
| assertEquals(expectedPlacePivots, placePivots); |
| |
| // Test individual facet.limit values |
| params.remove(FacetParams.FACET_LIMIT); |
| |
| params.set("f.place_t." + FacetParams.FACET_LIMIT, 1); |
| params.set("f.company_t." + FacetParams.FACET_LIMIT, 4); |
| |
| rsp = queryServer(params); |
| |
| expectedPlacePivots = new UnorderedEqualityArrayList<PivotField>(); |
| |
| expectedDublinPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "microsoft", |
| 4, null, null, createExpectedRange("price", 0, 100, 20, 2, 1, 0, |
| 0, 0))); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "polecat", |
| 4, null, null, createExpectedRange("price", 0, 100, 20, 2, 1, 0, |
| 0, 0))); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "null", 3, |
| null, null, createExpectedRange("price", 0, 100, 20, 1, 1, 0, 0, |
| 0))); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "fujitsu", |
| 2, null, null, createExpectedRange("price", 0, 100, 20, 0, 1, 0, |
| 0, 0))); |
| |
| expectedLondonPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "null", 3, |
| null, null, createExpectedRange("price", 0, 100, 20, 0, 2, 0, 0, |
| 0))); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "polecat", |
| 3, null, null, createExpectedRange("price", 0, 100, 20, 0, 2, 0, |
| 0, 0))); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "bbc", 2, |
| null, null, createExpectedRange("price", 0, 100, 20, 0, 1, 0, 0, |
| 0))); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "fujitsu", |
| 2, null, null, createExpectedRange("price", 0, 100, 20, 0, 1, 0, |
| 0, 0))); |
| |
| expectedCardiffPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedCardiffPivots.add(new ComparablePivotField("company_t", "polecat", |
| 3, null, null, createExpectedRange("price", 0, 100, 20, 1, 1, 0, |
| 0, 0))); |
| |
| expectedKrakowPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedKrakowPivots.add(new ComparablePivotField("company_t", "null", 3, |
| null, null, createExpectedRange("price", 0, 100, 20, 0, 1, 0, 0, |
| 0))); |
| |
| expectedLAPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedLAPivots.add(new ComparablePivotField("company_t", "fujitsu", 2, |
| null, null, createExpectedRange("price", 0, 100, 20, 0, 1, 0, 0, |
| 0))); |
| |
| expectedCorkPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedCorkPivots.add(new ComparablePivotField("company_t", "fujitsu", 1, |
| null, null, createExpectedRange("price", 0, 100, 20, 0, 0, 0, 0, |
| 0))); |
| |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "dublin", 4, |
| expectedDublinPivots, null, createExpectedRange("price", 0, 100, |
| 20, 2, 1, 0, 0, 0))); |
| |
| placePivots = rsp.getFacetPivot().get("place_t,company_t"); |
| assertEquals(expectedPlacePivots, placePivots); |
| |
| params.remove("f.company_t." + FacetParams.FACET_LIMIT); |
| params.remove("f.place_t." + FacetParams.FACET_LIMIT); |
| params.set(FacetParams.FACET_LIMIT, 2); |
| |
| // Test facet.missing=true with diff sorts |
| |
| index("id", 777); // NOTE: id=25 has no place as well |
| commit(); |
| |
| SolrParams missingA = params("q", "*:*", "rows", "0", "facet", "true", |
| "facet.pivot", "place_t,company_t", |
| // default facet.sort |
| FacetParams.FACET_MISSING, "true"); |
| SolrParams missingB = SolrParams.wrapDefaults(missingA, |
| params(FacetParams.FACET_LIMIT, "4", "facet.sort", "index")); |
| for (SolrParams p : new SolrParams[]{missingA, missingB}) { |
| // in either case, the last pivot option should be the same |
| rsp = query(p); |
| placePivots = rsp.getFacetPivot().get("place_t,company_t"); |
| assertTrue("not enough values for pivot: " + p + " => " + placePivots, |
| 1 < placePivots.size()); |
| PivotField missing = placePivots.get(placePivots.size() - 1); |
| assertNull("not the missing place value: " + p, missing.getValue()); |
| assertEquals("wrong missing place count: " + p, 2, missing.getCount()); |
| assertTrue("not enough sub-pivots for missing place: " + p + " => " |
| + missing.getPivot(), 1 < missing.getPivot().size()); |
| missing = missing.getPivot().get(missing.getPivot().size() - 1); |
| assertNull("not the missing company value: " + p, missing.getValue()); |
| assertEquals("wrong missing company count: " + p, 1, missing.getCount()); |
| assertNull("company shouldn't have sub-pivots: " + p, missing.getPivot()); |
| } |
| |
| // sort=index + mincount + limit |
| for (SolrParams variableParams : new SolrParams[]{ |
| // we should get the same results regardless of overrequest |
| params("facet.overrequest.count", "0", "facet.overrequest.ratio", "0"), |
| params()}) { |
| |
| SolrParams p = SolrParams.wrapDefaults( |
| params("q", "*:*", "rows", "0", "facet", "true", "facet.pivot", |
| "company_t", "facet.sort", "index", "facet.pivot.mincount", "4", |
| "facet.limit", "4"), variableParams); |
| |
| try { |
| List<PivotField> pivots = query(p).getFacetPivot().get("company_t"); |
| assertEquals(4, pivots.size()); |
| assertEquals("fujitsu", pivots.get(0).getValue()); |
| assertEquals(4, pivots.get(0).getCount()); |
| assertEquals("microsoft", pivots.get(1).getValue()); |
| assertEquals(5, pivots.get(1).getCount()); |
| assertEquals("null", pivots.get(2).getValue()); |
| assertEquals(6, pivots.get(2).getCount()); |
| assertEquals("polecat", pivots.get(3).getValue()); |
| assertEquals(6, pivots.get(3).getCount()); |
| |
| } catch (AssertionFailedError ae) { |
| throw new AssertionError(ae.getMessage() + " <== " + p.toString(), ae); |
| } |
| } |
| |
| // sort=index + mincount + limit + offset |
| for (SolrParams variableParams : new SolrParams[]{ |
| // we should get the same results regardless of overrequest |
| params("facet.overrequest.count", "0", "facet.overrequest.ratio", "0"), |
| params()}) { |
| |
| SolrParams p = SolrParams.wrapDefaults( |
| params("q", "*:*", "rows", "0", "facet", "true", "facet.pivot", |
| "company_t", "facet.sort", "index", "facet.pivot.mincount", "4", |
| "facet.offset", "1", "facet.limit", "4"), variableParams); |
| try { |
| List<PivotField> pivots = query(p).getFacetPivot().get("company_t"); |
| assertEquals(3, pivots.size()); // asked for 4, but not enough meet the |
| // mincount |
| assertEquals("microsoft", pivots.get(0).getValue()); |
| assertEquals(5, pivots.get(0).getCount()); |
| assertEquals("null", pivots.get(1).getValue()); |
| assertEquals(6, pivots.get(1).getCount()); |
| assertEquals("polecat", pivots.get(2).getValue()); |
| assertEquals(6, pivots.get(2).getCount()); |
| |
| } catch (AssertionFailedError ae) { |
| throw new AssertionError(ae.getMessage() + " <== " + p.toString(), ae); |
| } |
| |
| } |
| |
| // sort=index + mincount + limit + offset (more permutations) |
| for (SolrParams variableParams : new SolrParams[]{ |
| // all of these combinations should result in the same first value |
| params("facet.pivot.mincount", "4", "facet.offset", "2"), |
| params("facet.pivot.mincount", "5", "facet.offset", "1"), |
| params("facet.pivot.mincount", "6", "facet.offset", "0")}) { |
| |
| SolrParams p = SolrParams.wrapDefaults( |
| params("q", "*:*", "rows", "0", "facet", "true", "facet.limit", "1", |
| "facet.sort", "index", "facet.overrequest.ratio", "0", |
| "facet.pivot", "company_t"), variableParams); |
| |
| try { |
| List<PivotField> pivots = query(p).getFacetPivot().get("company_t"); |
| assertEquals(1, pivots.size()); |
| assertEquals(pivots.toString(), "null", pivots.get(0).getValue()); |
| assertEquals(pivots.toString(), 6, pivots.get(0).getCount()); |
| |
| } catch (AssertionFailedError ae) { |
| throw new AssertionError(ae.getMessage() + " <== " + p.toString(), ae); |
| } |
| } |
| } |
| |
| private void testFacetPivotQuery() throws Exception { |
| final ModifiableSolrParams params = new ModifiableSolrParams(); |
| setDistributedParams(params); |
| params.add("q", "*:*"); |
| params.add("facet", "true"); |
| params.add("facet.pivot", "{!query=s1}place_t,company_t"); |
| params.add("facet.query", "{!tag=s1 key=highPrice}price_ti:[25 TO 100]"); |
| |
| QueryResponse rsp = queryServer(params); |
| |
| List<PivotField> expectedPlacePivots = new UnorderedEqualityArrayList<PivotField>(); |
| List<PivotField> expectedCardiffPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedCardiffPivots.add(new ComparablePivotField("company_t", |
| "microsoft", 2, null, createExpectedQCount( |
| new String[]{"highPrice"}, new int[]{0}), null)); |
| expectedCardiffPivots.add(new ComparablePivotField("company_t", "null", 2, |
| null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{1}), null)); |
| expectedCardiffPivots.add(new ComparablePivotField("company_t", "bbc", 2, |
| null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{1}), null)); |
| expectedCardiffPivots.add(new ComparablePivotField("company_t", "polecat", |
| 3, null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{1}), null)); |
| expectedCardiffPivots.add(new ComparablePivotField("company_t", "fujitsu", |
| 1, null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{0}), null)); |
| List<PivotField> expectedDublinPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "polecat", |
| 4, null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{1}), null)); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "microsoft", |
| 4, null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{1}), null)); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "null", 3, |
| null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{1}), null)); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "fujitsu", |
| 2, null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{1}), null)); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "bbc", 1, |
| null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{0}), null)); |
| List<PivotField> expectedLondonPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "polecat", |
| 3, null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{2}), null)); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "microsoft", |
| 2, null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{1}), null)); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "fujitsu", |
| 2, null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{1}), null)); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "null", 3, |
| null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{2}), null)); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "bbc", 2, |
| null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{1}), null)); |
| List<PivotField> expectedLAPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedLAPivots.add(new ComparablePivotField("company_t", "microsoft", 2, |
| null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{1}), null)); |
| expectedLAPivots.add(new ComparablePivotField("company_t", "fujitsu", 2, |
| null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{1}), null)); |
| expectedLAPivots.add(new ComparablePivotField("company_t", "null", 2, null, |
| createExpectedQCount(new String[]{"highPrice"}, new int[]{1}), |
| null)); |
| expectedLAPivots.add(new ComparablePivotField("company_t", "bbc", 1, null, |
| createExpectedQCount(new String[]{"highPrice"}, new int[]{0}), |
| null)); |
| expectedLAPivots.add(new ComparablePivotField("company_t", "polecat", 2, |
| null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{1}), null)); |
| List<PivotField> expectedKrakowPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedKrakowPivots.add(new ComparablePivotField("company_t", "polecat", |
| 2, null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{1}), null)); |
| expectedKrakowPivots.add(new ComparablePivotField("company_t", "bbc", 2, |
| null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{1}), null)); |
| expectedKrakowPivots.add(new ComparablePivotField("company_t", "null", 3, |
| null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{1}), null)); |
| expectedKrakowPivots.add(new ComparablePivotField("company_t", "fujitsu", |
| 1, null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{0}), null)); |
| expectedKrakowPivots.add(new ComparablePivotField("company_t", "microsoft", |
| 1, null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{0}), null)); |
| List<PivotField> expectedCorkPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedCorkPivots.add(new ComparablePivotField("company_t", "fujitsu", 1, |
| null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{0}), null)); |
| expectedCorkPivots.add(new ComparablePivotField("company_t", "rte", 1, |
| null, createExpectedQCount(new String[]{"highPrice"}, |
| new int[]{0}), null)); |
| |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "dublin", 4, |
| expectedDublinPivots, createExpectedQCount( |
| new String[]{"highPrice"}, new int[]{1}), null)); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "cardiff", 3, |
| expectedCardiffPivots, createExpectedQCount( |
| new String[]{"highPrice"}, new int[]{1}), null)); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "london", 4, |
| expectedLondonPivots, createExpectedQCount( |
| new String[]{"highPrice"}, new int[]{3}), null)); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "la", 3, |
| expectedLAPivots, createExpectedQCount( |
| new String[]{"highPrice"}, new int[]{1}), null)); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "krakow", 3, |
| expectedKrakowPivots, createExpectedQCount( |
| new String[]{"highPrice"}, new int[]{1}), null)); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "cork", 1, |
| expectedCorkPivots, createExpectedQCount( |
| new String[]{"highPrice"}, new int[]{0}), null)); |
| |
| List<PivotField> placePivots = rsp.getFacetPivot().get("place_t,company_t"); |
| |
| // Useful to check for errors, orders lists and does toString() equality |
| // check |
| testOrderedPivotsStringEquality(expectedPlacePivots, placePivots); |
| |
| assertEquals(expectedPlacePivots, placePivots); |
| |
| // Add second query for low price |
| params.add("facet.query", "{!tag=s1 key=lowPrice}price_ti:[0 TO 20]"); |
| expectedPlacePivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedCardiffPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedCardiffPivots.add(new ComparablePivotField("company_t", |
| "microsoft", 2, null, createExpectedQCount(new String[]{ |
| "highPrice", "lowPrice"}, new int[]{0, 1}), null)); |
| expectedCardiffPivots.add(new ComparablePivotField("company_t", "null", 2, |
| null, createExpectedQCount( |
| new String[]{"highPrice", "lowPrice"}, new int[]{1, 0}), null)); |
| expectedCardiffPivots.add(new ComparablePivotField("company_t", "bbc", 2, |
| null, createExpectedQCount( |
| new String[]{"highPrice", "lowPrice"}, new int[]{1, 0}), null)); |
| expectedCardiffPivots.add(new ComparablePivotField("company_t", "polecat", |
| 3, null, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{1, 1}), null)); |
| expectedCardiffPivots.add(new ComparablePivotField("company_t", "fujitsu", |
| 1, null, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{0, 0}), null)); |
| expectedDublinPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "polecat", |
| 4, null, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{1, 2}), null)); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "microsoft", |
| 4, null, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{1, 2}), null)); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "null", 3, |
| null, createExpectedQCount( |
| new String[]{"highPrice", "lowPrice"}, new int[]{1, 1}), null)); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "fujitsu", |
| 2, null, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{1, 0}), null)); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "bbc", 1, |
| null, createExpectedQCount( |
| new String[]{"highPrice", "lowPrice"}, new int[]{0, 0}), null)); |
| expectedLondonPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "polecat", |
| 3, null, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{2, 0}), null)); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "microsoft", |
| 2, null, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{1, 0}), null)); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "fujitsu", |
| 2, null, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{1, 0}), null)); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "null", 3, |
| null, createExpectedQCount( |
| new String[]{"highPrice", "lowPrice"}, new int[]{2, 0}), null)); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "bbc", 2, |
| null, createExpectedQCount( |
| new String[]{"highPrice", "lowPrice"}, new int[]{1, 0}), null)); |
| expectedLAPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedLAPivots.add(new ComparablePivotField("company_t", "microsoft", 2, |
| null, createExpectedQCount( |
| new String[]{"highPrice", "lowPrice"}, new int[]{1, 0}), null)); |
| expectedLAPivots.add(new ComparablePivotField("company_t", "fujitsu", 2, |
| null, createExpectedQCount( |
| new String[]{"highPrice", "lowPrice"}, new int[]{1, 0}), null)); |
| expectedLAPivots.add(new ComparablePivotField("company_t", "null", 2, null, |
| createExpectedQCount(new String[]{"highPrice", "lowPrice"}, |
| new int[]{1, 0}), null)); |
| expectedLAPivots.add(new ComparablePivotField("company_t", "bbc", 1, null, |
| createExpectedQCount(new String[]{"highPrice", "lowPrice"}, |
| new int[]{0, 0}), null)); |
| expectedLAPivots.add(new ComparablePivotField("company_t", "polecat", 2, |
| null, createExpectedQCount( |
| new String[]{"highPrice", "lowPrice"}, new int[]{1, 0}), null)); |
| expectedKrakowPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedKrakowPivots.add(new ComparablePivotField("company_t", "polecat", |
| 2, null, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{1, 0}), null)); |
| expectedKrakowPivots.add(new ComparablePivotField("company_t", "bbc", 2, |
| null, createExpectedQCount( |
| new String[]{"highPrice", "lowPrice"}, new int[]{1, 0}), null)); |
| expectedKrakowPivots.add(new ComparablePivotField("company_t", "null", 3, |
| null, createExpectedQCount( |
| new String[]{"highPrice", "lowPrice"}, new int[]{1, 0}), null)); |
| expectedKrakowPivots.add(new ComparablePivotField("company_t", "fujitsu", |
| 1, null, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{0, 0}), null)); |
| expectedKrakowPivots.add(new ComparablePivotField("company_t", "microsoft", |
| 1, null, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{0, 0}), null)); |
| expectedCorkPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedCorkPivots.add(new ComparablePivotField("company_t", "fujitsu", 1, |
| null, createExpectedQCount( |
| new String[]{"highPrice", "lowPrice"}, new int[]{0, 0}), null)); |
| expectedCorkPivots.add(new ComparablePivotField("company_t", "rte", 1, |
| null, createExpectedQCount( |
| new String[]{"highPrice", "lowPrice"}, new int[]{0, 0}), null)); |
| |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "dublin", 4, |
| expectedDublinPivots, createExpectedQCount(new String[]{ |
| "highPrice", "lowPrice"}, new int[]{1, 2}), null)); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "cardiff", 3, |
| expectedCardiffPivots, createExpectedQCount(new String[]{ |
| "highPrice", "lowPrice"}, new int[]{1, 1}), null)); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "london", 4, |
| expectedLondonPivots, createExpectedQCount(new String[]{ |
| "highPrice", "lowPrice"}, new int[]{3, 0}), null)); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "la", 3, |
| expectedLAPivots, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{1, 0}), null)); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "krakow", 3, |
| expectedKrakowPivots, createExpectedQCount(new String[]{ |
| "highPrice", "lowPrice"}, new int[]{1, 0}), null)); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "cork", 1, |
| expectedCorkPivots, createExpectedQCount(new String[]{ |
| "highPrice", "lowPrice"}, new int[]{0, 0}), null)); |
| |
| rsp = queryServer(params); |
| |
| placePivots = rsp.getFacetPivot().get("place_t,company_t"); |
| |
| // Useful to check for errors, orders lists and does toString() equality |
| // check |
| testOrderedPivotsStringEquality(expectedPlacePivots, placePivots); |
| assertEquals(expectedPlacePivots, placePivots); |
| |
| // Test sorting by count |
| |
| params.set(FacetParams.FACET_SORT, FacetParams.FACET_SORT_COUNT); |
| |
| rsp = queryServer(params); |
| |
| placePivots = rsp.getFacetPivot().get("place_t,company_t"); |
| |
| testCountSorting(placePivots); |
| |
| // Test limit |
| |
| params.set(FacetParams.FACET_LIMIT, 2); |
| |
| rsp = queryServer(params); |
| |
| expectedPlacePivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedDublinPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "polecat", |
| 4, null, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{1, 2}), null)); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "microsoft", |
| 4, null, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{1, 2}), null)); |
| expectedLondonPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "null", 3, |
| null, createExpectedQCount( |
| new String[]{"highPrice", "lowPrice"}, new int[]{2, 0}), null)); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "polecat", |
| 3, null, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{2, 0}), null)); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "dublin", 4, |
| expectedDublinPivots, createExpectedQCount(new String[]{ |
| "highPrice", "lowPrice"}, new int[]{1, 2}), null)); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "london", 4, |
| expectedLondonPivots, createExpectedQCount(new String[]{ |
| "highPrice", "lowPrice"}, new int[]{3, 0}), null)); |
| |
| placePivots = rsp.getFacetPivot().get("place_t,company_t"); |
| |
| assertEquals(expectedPlacePivots, placePivots); |
| |
| // Test individual facet.limit values |
| params.remove(FacetParams.FACET_LIMIT); |
| |
| params.set("f.place_t." + FacetParams.FACET_LIMIT, 1); |
| params.set("f.company_t." + FacetParams.FACET_LIMIT, 4); |
| |
| rsp = queryServer(params); |
| |
| expectedPlacePivots = new UnorderedEqualityArrayList<PivotField>(); |
| |
| expectedDublinPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "microsoft", |
| 4, null, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{1, 2}), null)); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "polecat", |
| 4, null, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{1, 2}), null)); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "null", 3, |
| null, createExpectedQCount( |
| new String[]{"highPrice", "lowPrice"}, new int[]{1, 1}), null)); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "fujitsu", |
| 2, null, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{1, 0}), null)); |
| |
| expectedLondonPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "null", 3, |
| null, createExpectedQCount( |
| new String[]{"highPrice", "lowPrice"}, new int[]{2, 0}), null)); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "polecat", |
| 3, null, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{2, 0}), null)); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "bbc", 2, |
| null, createExpectedQCount( |
| new String[]{"highPrice", "lowPrice"}, new int[]{1, 0}), null)); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "fujitsu", |
| 2, null, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{1, 0}), null)); |
| |
| expectedCardiffPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedCardiffPivots.add(new ComparablePivotField("company_t", "polecat", |
| 3, null, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{1, 1}), null)); |
| |
| expectedKrakowPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedKrakowPivots.add(new ComparablePivotField("company_t", "null", 3, |
| null, createExpectedQCount( |
| new String[]{"highPrice", "lowPrice"}, new int[]{1, 0}), null)); |
| |
| expectedLAPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedLAPivots.add(new ComparablePivotField("company_t", "fujitsu", 2, |
| null, createExpectedQCount( |
| new String[]{"highPrice", "lowPrice"}, new int[]{1, 0}), null)); |
| |
| expectedCorkPivots = new UnorderedEqualityArrayList<PivotField>(); |
| expectedCorkPivots.add(new ComparablePivotField("company_t", "fujitsu", 1, |
| null, createExpectedQCount( |
| new String[]{"highPrice", "lowPrice"}, new int[]{0, 0}), null)); |
| |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "dublin", 4, |
| expectedDublinPivots, createExpectedQCount(new String[]{ |
| "highPrice", "lowPrice"}, new int[]{1, 2}), null)); |
| |
| placePivots = rsp.getFacetPivot().get("place_t,company_t"); |
| assertEquals(expectedPlacePivots, placePivots); |
| |
| params.remove("f.company_t." + FacetParams.FACET_LIMIT); |
| params.remove("f.place_t." + FacetParams.FACET_LIMIT); |
| params.set(FacetParams.FACET_LIMIT, 2); |
| |
| // Test facet.missing=true with diff sorts |
| |
| index("id", 777); // NOTE: id=25 has no place as well |
| commit(); |
| |
| SolrParams missingA = params("q", "*:*", "rows", "0", "facet", "true", |
| "facet.pivot", "place_t,company_t", |
| // default facet.sort |
| FacetParams.FACET_MISSING, "true"); |
| SolrParams missingB = SolrParams.wrapDefaults(missingA, |
| params(FacetParams.FACET_LIMIT, "4", "facet.sort", "index")); |
| for (SolrParams p : new SolrParams[]{missingA, missingB}) { |
| // in either case, the last pivot option should be the same |
| rsp = query(p); |
| placePivots = rsp.getFacetPivot().get("place_t,company_t"); |
| assertTrue("not enough values for pivot: " + p + " => " + placePivots, |
| 1 < placePivots.size()); |
| PivotField missing = placePivots.get(placePivots.size() - 1); |
| assertNull("not the missing place value: " + p, missing.getValue()); |
| assertEquals("wrong missing place count: " + p, 2, missing.getCount()); |
| assertTrue("not enough sub-pivots for missing place: " + p + " => " |
| + missing.getPivot(), 1 < missing.getPivot().size()); |
| missing = missing.getPivot().get(missing.getPivot().size() - 1); |
| assertNull("not the missing company value: " + p, missing.getValue()); |
| assertEquals("wrong missing company count: " + p, 1, missing.getCount()); |
| assertNull("company shouldn't have sub-pivots: " + p, missing.getPivot()); |
| } |
| |
| // sort=index + mincount + limit |
| for (SolrParams variableParams : new SolrParams[]{ |
| // we should get the same results regardless of overrequest |
| params("facet.overrequest.count", "0", "facet.overrequest.ratio", "0"), |
| params()}) { |
| |
| SolrParams p = SolrParams.wrapDefaults( |
| params("q", "*:*", "rows", "0", "facet", "true", "facet.pivot", |
| "company_t", "facet.sort", "index", "facet.pivot.mincount", "4", |
| "facet.limit", "4"), variableParams); |
| |
| try { |
| List<PivotField> pivots = query(p).getFacetPivot().get("company_t"); |
| assertEquals(4, pivots.size()); |
| assertEquals("fujitsu", pivots.get(0).getValue()); |
| assertEquals(4, pivots.get(0).getCount()); |
| assertEquals("microsoft", pivots.get(1).getValue()); |
| assertEquals(5, pivots.get(1).getCount()); |
| assertEquals("null", pivots.get(2).getValue()); |
| assertEquals(6, pivots.get(2).getCount()); |
| assertEquals("polecat", pivots.get(3).getValue()); |
| assertEquals(6, pivots.get(3).getCount()); |
| |
| } catch (AssertionFailedError ae) { |
| throw new AssertionError(ae.getMessage() + " <== " + p.toString(), ae); |
| } |
| } |
| |
| // sort=index + mincount + limit + offset |
| for (SolrParams variableParams : new SolrParams[]{ |
| // we should get the same results regardless of overrequest |
| params("facet.overrequest.count", "0", "facet.overrequest.ratio", "0"), |
| params()}) { |
| |
| SolrParams p = SolrParams.wrapDefaults( |
| params("q", "*:*", "rows", "0", "facet", "true", "facet.pivot", |
| "company_t", "facet.sort", "index", "facet.pivot.mincount", "4", |
| "facet.offset", "1", "facet.limit", "4"), variableParams); |
| try { |
| List<PivotField> pivots = query(p).getFacetPivot().get("company_t"); |
| assertEquals(3, pivots.size()); // asked for 4, but not enough meet the |
| // mincount |
| assertEquals("microsoft", pivots.get(0).getValue()); |
| assertEquals(5, pivots.get(0).getCount()); |
| assertEquals("null", pivots.get(1).getValue()); |
| assertEquals(6, pivots.get(1).getCount()); |
| assertEquals("polecat", pivots.get(2).getValue()); |
| assertEquals(6, pivots.get(2).getCount()); |
| |
| } catch (AssertionFailedError ae) { |
| throw new AssertionError(ae.getMessage() + " <== " + p.toString(), ae); |
| } |
| |
| } |
| |
| // sort=index + mincount + limit + offset (more permutations) |
| for (SolrParams variableParams : new SolrParams[]{ |
| // all of these combinations should result in the same first value |
| params("facet.pivot.mincount", "4", "facet.offset", "2"), |
| params("facet.pivot.mincount", "5", "facet.offset", "1"), |
| params("facet.pivot.mincount", "6", "facet.offset", "0")}) { |
| |
| SolrParams p = SolrParams.wrapDefaults( |
| params("q", "*:*", "rows", "0", "facet", "true", "facet.limit", "1", |
| "facet.sort", "index", "facet.overrequest.ratio", "0", |
| "facet.pivot", "company_t"), variableParams); |
| |
| try { |
| List<PivotField> pivots = query(p).getFacetPivot().get("company_t"); |
| assertEquals(1, pivots.size()); |
| assertEquals(pivots.toString(), "null", pivots.get(0).getValue()); |
| assertEquals(pivots.toString(), 6, pivots.get(0).getCount()); |
| |
| } catch (AssertionFailedError ae) { |
| throw new AssertionError(ae.getMessage() + " <== " + p.toString(), ae); |
| } |
| } |
| } |
| |
| private void testPivotFacetRangeAndQuery() throws Exception { |
| SolrParams params = params("q", "*:*", |
| "rows", "0", |
| "facet", "true", |
| "stats", "true", |
| "facet.pivot", "{!range=s1 query=s2 stats=s3}place_t,company_t", |
| "facet.range", "{!tag=s1 key=price}price_ti", |
| "facet.query", "{!tag=s2 key=highPrice}price_ti:[25 TO 100]", |
| "facet.query", "{!tag=s2 key=lowPrice}price_ti:[0 TO 20]", |
| "stats.field", ("{!tag=s3 key=avg_price}price_ti"), |
| "facet.range.start", "0", |
| "facet.range.end", "100", |
| "facet.range.gap", "20", |
| FacetParams.FACET_SORT, FacetParams.FACET_SORT_COUNT, |
| FacetParams.FACET_LIMIT, "2"); |
| |
| UnorderedEqualityArrayList<PivotField> expectedPlacePivots = new UnorderedEqualityArrayList<>(); |
| UnorderedEqualityArrayList<PivotField> expectedDublinPivots = new UnorderedEqualityArrayList<>(); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "polecat", |
| 4, null, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{1, 2}), createExpectedRange("price", 0, 100, 20, 2, 1, 0, |
| 0, 0))); |
| expectedDublinPivots.add(new ComparablePivotField("company_t", "microsoft", |
| 4, null, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{1, 2}), createExpectedRange("price", 0, 100, 20, 2, 1, 0, |
| 0, 0))); |
| UnorderedEqualityArrayList<PivotField> expectedLondonPivots = new UnorderedEqualityArrayList<>(); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "null", 3, |
| null, createExpectedQCount( |
| new String[]{"highPrice", "lowPrice"}, new int[]{2, 0}), createExpectedRange("price", 0, 100, 20, 0, 2, 0, 0, |
| 0))); |
| expectedLondonPivots.add(new ComparablePivotField("company_t", "polecat", |
| 3, null, createExpectedQCount(new String[]{"highPrice", |
| "lowPrice"}, new int[]{2, 0}), createExpectedRange("price", 0, 100, 20, 0, 2, 0, |
| 0, 0))); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "dublin", 4, |
| expectedDublinPivots, createExpectedQCount(new String[]{ |
| "highPrice", "lowPrice"}, new int[]{1, 2}), createExpectedRange("price", 0, 100, |
| 20, 2, 1, 0, 0, 0))); |
| expectedPlacePivots.add(new ComparablePivotField("place_t", "london", 4, |
| expectedLondonPivots, createExpectedQCount(new String[]{ |
| "highPrice", "lowPrice"}, new int[]{3, 0}), createExpectedRange("price", 0, 100, |
| 20, 0, 3, 0, 0, 0))); |
| |
| QueryResponse rsp = query(params); |
| List<PivotField> placePivots = rsp.getFacetPivot().get("place_t,company_t"); |
| assertEquals(expectedPlacePivots, placePivots); |
| |
| PivotField dublinPivotField = placePivots.get(0); |
| assertEquals("dublin", dublinPivotField.getValue()); |
| assertEquals(4, dublinPivotField.getCount()); |
| |
| PivotField microsoftPivotField = dublinPivotField.getPivot().get(0); |
| assertEquals("microsoft", microsoftPivotField.getValue()); |
| assertEquals(4, microsoftPivotField.getCount()); |
| |
| FieldStatsInfo dublinMicrosoftStatsInfo = microsoftPivotField.getFieldStatsInfo().get("avg_price"); |
| assertEquals(21.0, (double) dublinMicrosoftStatsInfo.getMean(), 0.1E-7); |
| assertEquals(15.0, dublinMicrosoftStatsInfo.getMin()); |
| assertEquals(29.0, dublinMicrosoftStatsInfo.getMax()); |
| assertEquals(3, (long) dublinMicrosoftStatsInfo.getCount()); |
| assertEquals(1, (long) dublinMicrosoftStatsInfo.getMissing()); |
| assertEquals(63.0, dublinMicrosoftStatsInfo.getSum()); |
| assertEquals(1427.0, dublinMicrosoftStatsInfo.getSumOfSquares(), 0.1E-7); |
| assertEquals(7.211102550927978, dublinMicrosoftStatsInfo.getStddev(), 0.1E-7); |
| } |
| |
| private void testNegativeFacetQuery() throws Exception { |
| // this should not hang facet.query under the pivot |
| SolrParams params = params("q", "*:*", |
| "rows", "0", |
| "stats", "true", |
| "facet.query", "{!tag=ttt}price_ti:[25 TO 100]", |
| "facet", "true", |
| "facet.pivot", "{!query=t}place_t,company_t"); |
| QueryResponse rsp = query(params); |
| |
| assertNullFacetTypeInsidePivot(FacetParams.FACET_QUERY, rsp.getFacetPivot().get("place_t,company_t")); |
| |
| params = params("q", "*:*", |
| "rows", "0", |
| "stats", "true", |
| "facet", "true", |
| "facet.pivot", "{!query=t}place_t,company_t"); |
| rsp = query(params); |
| assertNullFacetTypeInsidePivot(FacetParams.FACET_QUERY, rsp.getFacetPivot().get("place_t,company_t")); |
| |
| params = params("q", "*:*", |
| "rows", "0", |
| "facet.query", "{!tag=t}price_ti:[25 TO 100]", |
| "hang", "", // empty |
| "facet", "true", |
| "facet.pivot", "{!query=$hang}place_t,company_t"); |
| rsp = query(params); |
| assertNullFacetTypeInsidePivot(FacetParams.FACET_QUERY, rsp.getFacetPivot().get("place_t,company_t")); |
| |
| params = params("q", "*:*", |
| "rows", "0", |
| "facet.query", "{!tag=t}price_ti:[25 TO 100]", |
| "hang", "price_ti:[0 TO 20]", // with a query |
| "facet", "true", |
| "facet.pivot", "{!query=$hang}place_t,company_t"); |
| rsp = query(params); |
| // we aren't going to start calculating facet query unless the query is specified with a 'facet.query' param |
| // hence hanging an arbitrary query shouldn't work |
| assertNullFacetTypeInsidePivot(FacetParams.FACET_QUERY, rsp.getFacetPivot().get("place_t,company_t")); |
| } |
| |
| private void testNegativeRangeQuery() throws Exception { |
| SolrParams params = params("q", "*:*", |
| "rows", "0", |
| "stats", "true", |
| "facet.range", "{!tag=s1 key=price}price_ti", |
| "facet", "true", |
| "facet.pivot", "{!range=s}place_t,company_t", |
| "facet.range.start", "0", |
| "facet.range.end", "100", |
| "facet.range.gap", "20"); |
| QueryResponse rsp = query(params); |
| assertNullFacetTypeInsidePivot(FacetParams.FACET_RANGE, rsp.getFacetPivot().get("place_t,company_t")); |
| |
| params = params("q", "*:*", |
| "rows", "0", |
| "stats", "true", |
| "facet.range", "{!tag=s1 key=price}price_ti", |
| "facet", "true", |
| "hang", "", // empty! |
| "facet.pivot", "{!range=$hang}place_t,company_t", |
| "facet.range.start", "0", |
| "facet.range.end", "100", |
| "facet.range.gap", "20"); |
| rsp = query(params); |
| assertNullFacetTypeInsidePivot(FacetParams.FACET_RANGE, rsp.getFacetPivot().get("place_t,company_t")); |
| |
| params = params("q", "*:*", |
| "rows", "0", |
| "stats", "true", |
| "facet.range", "{!tag=s1 key=price}price_ti", |
| "facet", "true", |
| "hang", "price_ti", |
| "facet.pivot", "{!range=$hang}place_t,company_t", |
| "facet.range.start", "0", |
| "facet.range.end", "100", |
| "facet.range.gap", "20"); |
| rsp = query(params); |
| assertNullFacetTypeInsidePivot(FacetParams.FACET_RANGE, rsp.getFacetPivot().get("place_t,company_t")); |
| } |
| |
| private Map<String, Integer> createExpectedQCount(String[] keys, int[] counts) { |
| Map<String, Integer> expectedQCounts = new LinkedHashMap<>(); |
| for (int idx = 0; idx < keys.length; idx++) { |
| expectedQCounts.put(keys[idx], counts[idx]); |
| } |
| return expectedQCounts; |
| } |
| |
| private void assertNullFacetTypeInsidePivot(String facetType, List<PivotField> pivots) { |
| for (PivotField pivot : pivots) { |
| if (facetType == FacetParams.FACET_QUERY) { |
| assertNull("pivot=" + pivot + " facetType=" + facetType |
| + " should've been null. Found: " + pivot.getFacetQuery(), pivot.getFacetQuery()); |
| } else if (facetType == FacetParams.FACET_RANGE) { |
| assertNull("pivot=" + pivot + " facetType=" + facetType |
| + " should've been null. Found: " + pivot.getFacetRanges(), pivot.getFacetRanges()); |
| } |
| |
| if (pivot.getPivot() != null) { |
| assertNullFacetTypeInsidePivot(facetType, pivot.getPivot()); |
| } |
| } |
| } |
| |
| // Useful to check for errors, orders lists and does toString() equality check |
| private void testOrderedPivotsStringEquality( |
| List<PivotField> expectedPlacePivots, List<PivotField> placePivots) { |
| Collections.sort(expectedPlacePivots, new PivotFieldComparator()); |
| for (PivotField expectedPivot : expectedPlacePivots) { |
| if (expectedPivot.getPivot() != null) { |
| Collections.sort(expectedPivot.getPivot(), new PivotFieldComparator()); |
| } |
| } |
| Collections.sort(placePivots, new PivotFieldComparator()); |
| for (PivotField pivot : placePivots) { |
| if (pivot.getPivot() != null) { |
| Collections.sort(pivot.getPivot(), new PivotFieldComparator()); |
| } |
| } |
| assertEquals(expectedPlacePivots.toString(), placePivots.toString()); |
| } |
| |
| /** |
| * sanity check the stat values nested under a pivot when at least one shard |
| * has nothing but missing values for the stat |
| */ |
| private void doTestPivotStatsFromOneShard() throws Exception { |
| SolrParams params = params("q", "*:*", "rows", "0", |
| "facet", "true", "stats", "true", |
| "facet.pivot", "{!stats=s1}place_t,company_t", |
| "stats.field", "{!tag=s1}solo_i", |
| "stats.field", "{!tag=s1}solo_s", |
| "stats.field", "{!tag=s1}solo_dt"); |
| |
| QueryResponse rsp = query(params); |
| |
| List<PivotField> placePivots = rsp.getFacetPivot().get("place_t,company_t"); |
| |
| PivotField placePivot = placePivots.get(0); |
| assertEquals("dublin", placePivot.getValue()); |
| assertEquals(4, placePivot.getCount()); |
| |
| PivotField companyPivot = placePivot.getPivot().get(2); |
| assertEquals("null", companyPivot.getValue()); |
| assertEquals(3, companyPivot.getCount()); |
| |
| for (PivotField pf : new PivotField[] { placePivot, companyPivot }) { |
| assertThereCanBeOnlyOne(pf, pf.getFieldStatsInfo().get("solo_s"), "lonely"); |
| |
| assertThereCanBeOnlyOne(pf, pf.getFieldStatsInfo().get("solo_i"), 42.0D); |
| assertEquals(pf.getField()+":"+pf.getValue()+": int mean", |
| 42.0D, pf.getFieldStatsInfo().get("solo_i").getMean()); |
| |
| Object expected = new Date(194923425000L); // 1976-03-06T01:23:45Z |
| assertThereCanBeOnlyOne(pf, pf.getFieldStatsInfo().get("solo_dt"), expected); |
| assertEquals(pf.getField()+":"+pf.getValue()+": date mean", |
| expected, pf.getFieldStatsInfo().get("solo_dt").getMean()); |
| |
| // TODO: add enum field asserts - blocked by SOLR-6682 |
| } |
| } |
| |
| private void testCountSorting(List<PivotField> pivots) { |
| Integer lastCount = null; |
| for (PivotField pivot : pivots) { |
| if (lastCount != null) { |
| assertTrue(pivot.getCount() <= lastCount); |
| } |
| lastCount = pivot.getCount(); |
| if (pivot.getPivot() != null) { |
| testCountSorting(pivot.getPivot()); |
| } |
| } |
| } |
| |
| /** |
| * given a PivotField, a FieldStatsInfo, and a value; asserts that: |
| * <ul> |
| * <li>stat count == 1</li> |
| * <li>stat missing == pivot count - 1</li> |
| * <li>stat min == stat max == value</li> |
| * </ul> |
| */ |
| private void assertThereCanBeOnlyOne(PivotField pf, FieldStatsInfo stats, Object val) { |
| String msg = pf.getField() + ":" + pf.getValue(); |
| assertEquals(msg + " stats count", 1L, (long) stats.getCount()); |
| assertEquals(msg + " stats missing", pf.getCount()-1L, (long) stats.getMissing()); |
| assertEquals(msg + " stats min", val, stats.getMin()); |
| assertEquals(msg + " stats max", val, stats.getMax()); |
| } |
| |
| @SuppressWarnings({"rawtypes"}) |
| private List<RangeFacet> createExpectedRange(String key, int start, int end, |
| int gap, int... values) { |
| List<RangeFacet> expectedRanges = new ArrayList<>(); |
| RangeFacet expectedPrices = new RangeFacet.Numeric(key, start, end, gap, null, null, null); |
| expectedRanges.add(expectedPrices); |
| int idx = 0; |
| for (int range = start; range < end; range += gap) { |
| expectedPrices.addCount(String.valueOf(range), values[idx]); |
| if (idx < values.length) { |
| idx++; |
| } |
| } |
| return expectedRanges; |
| } |
| |
| public static class ComparablePivotField extends PivotField { |
| |
| public ComparablePivotField(String f, Object v, int count, |
| List<PivotField> pivot, Map<String,Integer> queryCounts, |
| @SuppressWarnings({"rawtypes"})List<RangeFacet> ranges) { |
| super(f, v, count, pivot, null, queryCounts, ranges); |
| } |
| |
| public ComparablePivotField(String f, Object v, int count, |
| List<PivotField> pivot) { |
| super(f, v, count, pivot, null, null, null); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) return true; |
| if (obj == null) return false; |
| if (!obj.getClass().isAssignableFrom(PivotField.class)) return false; |
| PivotField other = (PivotField) obj; |
| if (getCount() != other.getCount()) return false; |
| if (getField() == null) { |
| if (other.getField() != null) return false; |
| } else if (!getField().equals(other.getField())) return false; |
| if (getPivot() == null) { |
| if (other.getPivot() != null) return false; |
| } else if (!getPivot().equals(other.getPivot())) return false; |
| if (getValue() == null) { |
| if (other.getValue() != null) return false; |
| } else if (!getValue().equals(other.getValue())) return false; |
| if (getFacetRanges() == null) { |
| if (other.getFacetRanges() != null) return false; |
| } else { |
| if (getFacetRanges().size() != other.getFacetRanges().size()) return false; |
| for (@SuppressWarnings({"rawtypes"})RangeFacet entry : getFacetRanges()) { |
| boolean found = false; |
| for (@SuppressWarnings({"rawtypes"})RangeFacet otherRange : other.getFacetRanges()) { |
| if (otherRange.getName().equals(entry.getName())) { |
| found = true; |
| |
| if (!entry.getGap().equals(otherRange.getGap())) return false; |
| if (!entry.getStart().equals(otherRange.getStart())) return false; |
| if (!entry.getEnd().equals(otherRange.getEnd())) return false; |
| |
| @SuppressWarnings({"unchecked"}) |
| List<RangeFacet.Count> myCounts = entry.getCounts(); |
| @SuppressWarnings({"unchecked"}) |
| List<RangeFacet.Count> otherRangeCounts = otherRange.getCounts(); |
| if ( (myCounts == null && otherRangeCounts != null) |
| || (myCounts != null && otherRangeCounts == null) |
| || (myCounts.size() != otherRangeCounts.size())) return false; |
| |
| for (int i=0; i<myCounts.size(); i++) { |
| if (!myCounts.get(i).getValue().equals(otherRangeCounts.get(i).getValue())) return false; |
| if (myCounts.get(i).getCount() != otherRangeCounts.get(i).getCount()) return false; |
| } |
| } |
| } |
| if (!found) return false; |
| } |
| } |
| if (getFacetQuery() == null) { |
| if (other.getFacetQuery() != null) return false; |
| } else { |
| if (getFacetQuery().size() != other.getFacetQuery().size()) return false; |
| for (Map.Entry<String,Integer> entry : getFacetQuery().entrySet()) { |
| Integer otherQCount = other.getFacetQuery().get(entry.getKey()); |
| if (otherQCount == null || !otherQCount.equals(entry.getValue())) return false; |
| } |
| } |
| return true; |
| } |
| |
| @Override |
| public int hashCode() { |
| throw new UnsupportedOperationException("Calling hashCode in ComparablePivotField"); |
| } |
| } |
| |
| public static class UnorderedEqualityArrayList<T> extends ArrayList<T> { |
| |
| @Override |
| public int hashCode() { |
| throw new UnsupportedOperationException("Calling hashCode in UnorderedEqualityArrayList"); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| boolean equal = false; |
| if (o instanceof ArrayList) { |
| List<?> otherList = (List<?>) o; |
| if (size() == otherList.size()) { |
| equal = true; |
| for (Object objectInOtherList : otherList) { |
| if (!contains(objectInOtherList)) { |
| return false; |
| } |
| } |
| } |
| } |
| return equal; |
| } |
| |
| public int indexOf(Object o) { |
| for (int i = 0; i < size(); i++) { |
| if (get(i).equals(o)) { |
| return i; |
| } |
| } |
| return -1; |
| } |
| } |
| |
| public static class PivotFieldComparator implements Comparator<PivotField> { |
| |
| @Override |
| public int compare(PivotField o1, PivotField o2) { |
| int compare = Integer.compare(o2.getCount(), o1.getCount()); |
| if (compare == 0) { |
| compare = ((String) o2.getValue()).compareTo((String) o1.getValue()); |
| } |
| if (compare == 0) { |
| for (Map.Entry<String,Integer> entry : o1.getFacetQuery().entrySet()) { |
| compare = entry.getValue().compareTo( |
| o2.getFacetQuery().get(entry.getKey())); |
| if (compare != 0) { |
| break; |
| } |
| } |
| if (compare == 0) { |
| compare = Integer.compare(o1.getFacetQuery().size(), |
| o2.getFacetQuery().size()); |
| } |
| } |
| if (compare == 0) { |
| for (@SuppressWarnings({"rawtypes"})RangeFacet entry : o1.getFacetRanges()) { |
| boolean found = false; |
| for (@SuppressWarnings({"rawtypes"})RangeFacet otherRangeFacet : o2.getFacetRanges()) { |
| if (otherRangeFacet.getName().equals(entry.getName())) { |
| found = true; |
| } |
| } |
| if (!found) { |
| compare = 1; |
| break; |
| } |
| } |
| } |
| return compare; |
| } |
| |
| } |
| |
| } |