1 package org.apache.lucene.facet.search;
3 import java.io.IOException;
6 import org.apache.lucene.index.IndexReader;
8 import org.apache.lucene.facet.search.params.FacetSearchParams;
9 import org.apache.lucene.facet.search.params.FacetRequest;
10 import org.apache.lucene.facet.search.results.FacetResult;
11 import org.apache.lucene.facet.taxonomy.TaxonomyReader;
14 * Licensed to the Apache Software Foundation (ASF) under one or more
15 * contributor license agreements. See the NOTICE file distributed with
16 * this work for additional information regarding copyright ownership.
17 * The ASF licenses this file to You under the Apache License, Version 2.0
18 * (the "License"); you may not use this file except in compliance with
19 * the License. You may obtain a copy of the License at
21 * http://www.apache.org/licenses/LICENSE-2.0
23 * Unless required by applicable law or agreed to in writing, software
24 * distributed under the License is distributed on an "AS IS" BASIS,
25 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26 * See the License for the specific language governing permissions and
27 * limitations under the License.
31 * Driver for Accumulating facets of faceted search requests over given
34 * @lucene.experimental
36 public abstract class FacetsAccumulator {
39 * Default threshold for using the complements optimization.
40 * If accumulating facets for a document set larger than this ratio of the index size than
41 * perform the complement optimization.
42 * @see #setComplementThreshold(double) for more info on the complements optimization.
44 public static final double DEFAULT_COMPLEMENT_THRESHOLD = 0.6;
47 * Passing this to {@link #setComplementThreshold(double)} will disable using complement optimization.
49 public static final double DISABLE_COMPLEMENT = Double.POSITIVE_INFINITY; // > 1 actually
52 * Passing this to {@link #setComplementThreshold(double)} will force using complement optimization.
54 public static final double FORCE_COMPLEMENT = 0; // <=0
56 private double complementThreshold = DEFAULT_COMPLEMENT_THRESHOLD;
58 protected final TaxonomyReader taxonomyReader;
59 protected final IndexReader indexReader;
60 protected FacetSearchParams searchParams;
62 private boolean allowLabeling = true;
64 public FacetsAccumulator(FacetSearchParams searchParams,
65 IndexReader indexReader,
66 TaxonomyReader taxonomyReader) {
67 this.indexReader = indexReader;
68 this.taxonomyReader = taxonomyReader;
69 this.searchParams = searchParams;
73 * Accumulate facets over given documents, according to facet requests in effect.
74 * @param docids documents (and their scores) for which facets are Accumulated.
75 * @return Accumulated facets.
76 * @throws IOException on error.
78 // internal API note: it was considered to move the docids into the constructor as well,
79 // but this prevents nice extension capabilities, especially in the way that
80 // Sampling Accumulator works with the (any) delegated accumulator.
81 public abstract List<FacetResult> accumulate(ScoredDocIDs docids) throws IOException;
84 * @return the complement threshold
85 * @see #setComplementThreshold(double)
87 public double getComplementThreshold() {
88 return complementThreshold;
92 * Set the complement threshold.
93 * This threshold will dictate whether the complements optimization is applied.
94 * The optimization is to count for less documents. It is useful when the same
95 * FacetSearchParams are used for varying sets of documents. The first time
96 * complements is used the "total counts" are computed - counting for all the
97 * documents in the collection. Then, only the complementing set of documents
98 * is considered, and used to decrement from the overall counts, thereby
99 * walking through less documents, which is faster.
101 * Note that this optimization is only available when searching an index
102 * whose {@link IndexReader} implements both
103 * {@link IndexReader#directory()} and {@link IndexReader#getVersion()}
104 * otherwise the optimization is silently disabled regardless of
105 * the complement threshold settings.
107 * For the default settings see {@link #DEFAULT_COMPLEMENT_THRESHOLD}.
109 * To forcing complements in all cases pass {@link #FORCE_COMPLEMENT}.
110 * This is mostly useful for testing purposes, as forcing complements when only
111 * tiny fraction of available documents match the query does not make sense and
112 * would incur performance degradations.
114 * To disable complements pass {@link #DISABLE_COMPLEMENT}.
115 * @param complementThreshold the complement threshold to set
117 public void setComplementThreshold(double complementThreshold) {
118 this.complementThreshold = complementThreshold;
122 * Check if labeling is allowed for this accumulator.
124 * By default labeling is allowed.
125 * This allows one accumulator to invoke other accumulators for accumulation
126 * but keep to itself the responsibility of labeling.
127 * This might br handy since labeling is a costly operation.
128 * @return true of labeling is allowed for this accumulator
129 * @see #setAllowLabeling(boolean)
131 protected boolean isAllowLabeling() {
132 return allowLabeling;
136 * Set whether labeling is allowed for this accumulator.
137 * @param allowLabeling new setting for allow labeling
138 * @see #isAllowLabeling()
140 protected void setAllowLabeling(boolean allowLabeling) {
141 this.allowLabeling = allowLabeling;
144 /** check if all requests are complementable */
145 protected boolean mayComplement() {
146 for (FacetRequest freq:searchParams.getFacetRequests()) {
147 if (!freq.supportsComplements()) {