/** * A recursive method for generating <code>NamedLists</code> from this field suitable for * including in a pivot facet response to the original distributed request. */ public List<NamedList<Object>> convertToListOfNamedLists() { List<NamedList<Object>> convertedPivotList = null; if (valueCollection.size() > 0) { convertedPivotList = new LinkedList<>(); for (PivotFacetValue pivot : valueCollection) convertedPivotList.add(pivot.convertToNamedList()); } return convertedPivotList; }
/** * A recursive method to construct a new <code>PivotFacetField</code> object from the contents of * the {@link NamedList}s provided by the specified shard, relative to a parent value (if this is * not the top field in the pivot hierarchy) * * <p>The associated child {@link PivotFacetValue}s will be recursively built as well. * * @see PivotFacetValue#createFromNamedList * @param shardNumber the id of the shard that provided this data * @param rb The response builder of the current request * @param owner the parent value in the current pivot (may be null) * @param pivotValues the data from the specified shard for this pivot field, may be null or empty * @return the new PivotFacetField, null if pivotValues is null or empty. */ public static PivotFacetField createFromListOfNamedLists( int shardNumber, ResponseBuilder rb, PivotFacetValue owner, List<NamedList<Object>> pivotValues) { if (null == pivotValues || pivotValues.size() <= 0) return null; NamedList<Object> firstValue = pivotValues.get(0); PivotFacetField createdPivotFacetField = new PivotFacetField(rb, owner, PivotFacetHelper.getField(firstValue)); int lowestCount = Integer.MAX_VALUE; for (NamedList<Object> pivotValue : pivotValues) { lowestCount = Math.min(lowestCount, PivotFacetHelper.getCount(pivotValue)); PivotFacetValue newValue = PivotFacetValue.createFromNamedList(shardNumber, rb, createdPivotFacetField, pivotValue); createdPivotFacetField.valueCollection.add(newValue); } createdPivotFacetField.shardLowestCount.put(shardNumber, lowestCount); createdPivotFacetField.numberOfValuesContributedByShard.put(shardNumber, pivotValues.size()); return createdPivotFacetField; }
/** * Checks the {@link #lowestCountContributedbyShard} for each shard, combined with the counts we * already know, to see if this value is a viable candidate -- <b>Does not make sense when using * {@link FacetParams#FACET_SORT_INDEX}</b> * * @see #processDefiniteCandidateElement */ private void processPossibleCandidateElement( PivotFacet pf, PivotFacetValue value, final int refinementThreshold) { assert FacetParams.FACET_SORT_COUNT.equals(facetFieldSort) : "Method only makes sense when sorting by count"; int maxPossibleCountAfterRefinement = value.getCount(); for (int shard = pf.knownShards.nextSetBit(0); 0 <= shard; shard = pf.knownShards.nextSetBit(shard + 1)) { if (!value.shardHasContributed(shard)) { maxPossibleCountAfterRefinement += lowestCountContributedbyShard(shard); } } if (refinementThreshold <= maxPossibleCountAfterRefinement) { processDefiniteCandidateElement(pf, value); } }
private void contributeValueFromShard( int shardNumber, ResponseBuilder rb, NamedList<Object> shardValue) { incrementShardValueCount(shardNumber); Comparable value = PivotFacetHelper.getValue(shardValue); int count = PivotFacetHelper.getCount(shardValue); // We're changing values so we most mark the collection as dirty valueCollection.markDirty(); if ((!shardLowestCount.containsKey(shardNumber)) || shardLowestCount.get(shardNumber) > count) { shardLowestCount.put(shardNumber, count); } PivotFacetValue facetValue = valueCollection.get(value); if (null == facetValue) { // never seen before, we need to create it from scratch facetValue = PivotFacetValue.createFromNamedList(shardNumber, rb, this, shardValue); this.valueCollection.add(facetValue); } else { facetValue.mergeContributionFromShard(shardNumber, rb, shardValue); } }
/** * Adds refinement requests for the value for each shard that has not already contributed a count * for this value. */ private void processDefiniteCandidateElement(PivotFacet pf, PivotFacetValue value) { for (int shard = pf.knownShards.nextSetBit(0); 0 <= shard; shard = pf.knownShards.nextSetBit(shard + 1)) { if (!value.shardHasContributed(shard)) { if ( // if we're doing index order, we need to refine anything // (mincount may have excluded from a shard) FacetParams.FACET_SORT_INDEX.equals(facetFieldSort) // if we are doing count order, we need to refine if the limit was hit // (if not, the shard doesn't have the value or it would have returned already) || numberOfValuesContributedByShardWasLimitedByFacetFieldLimit(shard)) { pf.addRefinement(shard, value); } } } }
private void refineNextLevelOfFacets(PivotFacet pf) { List<PivotFacetValue> explicitValsToRefine = valueCollection.getNextLevelValuesToRefine(); for (PivotFacetValue value : explicitValsToRefine) { if (null != value.getChildPivot()) { value.getChildPivot().queuePivotRefinementRequests(pf); } } PivotFacetValue missing = this.valueCollection.getMissingValue(); if (null != missing && null != missing.getChildPivot()) { missing.getChildPivot().queuePivotRefinementRequests(pf); } }
/** * A recursive method that walks up the tree of pivot fields/values to build a list of String * representations of the values that lead down to this PivotFacetField. * * @return A mutable List of the pivot values leading down to this pivot field, will never be null * but may contain nulls and may be empty if this is a top level pivot field * @see PivotFacetValue#getValuePath */ public List<String> getValuePath() { if (null != parentValue) { return parentValue.getValuePath(); } return new ArrayList<String>(3); }
/** * A recursive method to construct a new <code>PivotFacetValue</code> object from the contents of * the {@link NamedList} provided by the specified shard, relative to the specified field. * * <p>If the <code>NamedList</code> contains data for a child {@link PivotFacetField} that will be * recursively built as well. * * @see PivotFacetField#createFromListOfNamedLists * @param shardNumber the id of the shard that provided this data * @param rb The response builder of the current request * @param parentField the parent field in the current pivot associated with this value * @param pivotData the data from the specified shard for this pivot value */ @SuppressWarnings("unchecked") public static PivotFacetValue createFromNamedList( int shardNumber, ResponseBuilder rb, PivotFacetField parentField, NamedList<Object> pivotData) { Comparable pivotVal = null; int pivotCount = 0; List<NamedList<Object>> childPivotData = null; NamedList<NamedList<NamedList<?>>> statsValues = null; NamedList<Number> queryCounts = null; SimpleOrderedMap<SimpleOrderedMap<Object>> ranges = null; for (int i = 0; i < pivotData.size(); i++) { String key = pivotData.getName(i); Object value = pivotData.getVal(i); PivotListEntry entry = PivotListEntry.get(key); switch (entry) { case VALUE: pivotVal = (Comparable) value; break; case FIELD: assert parentField.field.equals(value) : "Parent Field mismatch: " + parentField.field + "!=" + value; break; case COUNT: pivotCount = (Integer) value; break; case PIVOT: childPivotData = (List<NamedList<Object>>) value; break; case STATS: statsValues = (NamedList<NamedList<NamedList<?>>>) value; break; case QUERIES: queryCounts = (NamedList<Number>) value; break; case RANGES: ranges = (SimpleOrderedMap<SimpleOrderedMap<Object>>) value; break; default: throw new RuntimeException("PivotListEntry contains unaccounted for item: " + entry); } } PivotFacetValue newPivotFacet = new PivotFacetValue(parentField, pivotVal); newPivotFacet.count = pivotCount; newPivotFacet.sourceShards.set(shardNumber); if (statsValues != null) { newPivotFacet.statsValues = PivotFacetHelper.mergeStats(null, statsValues, rb._statsInfo); } if (queryCounts != null) { newPivotFacet.queryCounts = PivotFacetHelper.mergeQueryCounts(null, queryCounts); } if (ranges != null) { newPivotFacet.rangeCounts = new LinkedHashMap<>(); RangeFacetRequest.DistribRangeFacet.mergeFacetRangesFromShardResponse( newPivotFacet.rangeCounts, ranges); } newPivotFacet.childPivot = PivotFacetField.createFromListOfNamedLists(shardNumber, rb, newPivotFacet, childPivotData); return newPivotFacet; }