LUCENE-5136: improve FacetRequest javadocs

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1507194 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Shai Erera 2013-07-26 05:01:44 +00:00
parent 6e56ccd030
commit c74f89adc4
1 changed files with 99 additions and 102 deletions

View File

@ -2,6 +2,7 @@ package org.apache.lucene.facet.search;
import java.io.IOException; import java.io.IOException;
import org.apache.lucene.facet.params.CategoryListParams.OrdinalPolicy;
import org.apache.lucene.facet.taxonomy.CategoryPath; import org.apache.lucene.facet.taxonomy.CategoryPath;
import org.apache.lucene.facet.taxonomy.TaxonomyReader; import org.apache.lucene.facet.taxonomy.TaxonomyReader;
@ -23,30 +24,36 @@ import org.apache.lucene.facet.taxonomy.TaxonomyReader;
*/ */
/** /**
* Request to accumulate facet information for a specified facet and possibly * Defines an aggregation request for a category. Allows specifying the
* also some of its descendants, upto a specified depth. * {@link #numResults number of child categories} to return as well as
* {@link #getSortOrder() which} categories to consider the "top" (highest or
* lowest ranking ones).
* <p> * <p>
* The facet request additionally defines what information should * If the category being aggregated is hierarchical, you can also specify the
* be computed within the facet results, if and how should results * {@link #setDepth(int) depth} up which to aggregate child categories as well
* be ordered, etc. * as how the result should be {@link #setResultMode(ResultMode) constructed}.
* <P>
* An example facet request is to look at all sub-categories of "Author", and
* return the 10 with the highest counts (sorted by decreasing count).
* *
* @lucene.experimental * @lucene.experimental
*/ */
public abstract class FacetRequest { public abstract class FacetRequest {
/** /**
* Result structure manner of applying request's limits such as * When {@link FacetRequest#getDepth()} is greater than 1, defines the
* {@link FacetRequest#getNumLabel()} and {@link FacetRequest#numResults}. * structure of the result as well as how constraints such as
* Only relevant when {@link FacetRequest#getDepth()} is &gt; 1. * {@link FacetRequest#numResults} and {@link FacetRequest#getNumLabel()} are
* applied.
*/ */
public enum ResultMode { public enum ResultMode {
/** Limits are applied per node, and the result has a full tree structure. */ /**
* Constraints are applied per node, and the result has a full tree
* structure. Default result mode.
*/
PER_NODE_IN_TREE, PER_NODE_IN_TREE,
/** Limits are applied globally, on total number of results, and the result has a flat structure. */ /**
* Constraints are applied globally, on total number of results, and the
* result has a flat structure.
*/
GLOBAL_FLAT GLOBAL_FLAT
} }
@ -54,59 +61,50 @@ public abstract class FacetRequest {
* Specifies which array of {@link FacetArrays} should be used to resolve * Specifies which array of {@link FacetArrays} should be used to resolve
* values. When set to {@link #INT} or {@link #FLOAT}, allows creating an * values. When set to {@link #INT} or {@link #FLOAT}, allows creating an
* optimized {@link FacetResultsHandler}, which does not call * optimized {@link FacetResultsHandler}, which does not call
* {@link FacetRequest#getValueOf(FacetArrays, int)} for every ordinals. * {@link FacetRequest#getValueOf(FacetArrays, int)} for every ordinal.
* <p> * <p>
* If set to {@link #BOTH}, the {@link FacetResultsHandler} will use * If set to {@link #BOTH}, the {@link FacetResultsHandler} will use
* {@link FacetRequest#getValueOf(FacetArrays, int)} to resolve ordinal * {@link FacetRequest#getValueOf(FacetArrays, int)} to resolve ordinal
* values, although it is recommended that you consider writing a specialized * values, although it is recommended that you consider writing a specialized
* {@link FacetResultsHandler}. * {@link FacetResultsHandler}.
* <p>
* Can also be set to {@link #NONE}, to indicate that this
* {@link FacetRequest} does not use {@link FacetArrays} to aggregate its
* result categories. Such requests won't use {@link FacetResultsHandler}.
*/ */
public enum FacetArraysSource { INT, FLOAT, BOTH } public enum FacetArraysSource { INT, FLOAT, BOTH, NONE }
/** Requested sort order for the results. */ /**
* Defines which categories to return. If {@link #DESCENDING} (the default),
* the highest {@link FacetRequest#numResults} weighted categories will be
* returned, otherwise the lowest ones.
*/
public enum SortOrder { ASCENDING, DESCENDING } public enum SortOrder { ASCENDING, DESCENDING }
/** /** The category being aggregated in this facet request. */
* Default depth for facets accumulation.
* @see #getDepth()
*/
public static final int DEFAULT_DEPTH = 1;
/**
* Default result mode
* @see #getResultMode()
*/
public static final ResultMode DEFAULT_RESULT_MODE = ResultMode.PER_NODE_IN_TREE;
public final CategoryPath categoryPath; public final CategoryPath categoryPath;
/** The number of child categories to return for {@link #categoryPath}. */
public final int numResults; public final int numResults;
private int numLabel; private int numLabel;
private int depth; private int depth = 1;
private SortOrder sortOrder; private SortOrder sortOrder = SortOrder.DESCENDING;
private ResultMode resultMode = ResultMode.PER_NODE_IN_TREE;
/** // Computed at construction; based on categoryPath and numResults.
* Computed at construction, this hashCode is based on two final members
* {@link CategoryPath} and <code>numResults</code>
*/
private final int hashCode; private final int hashCode;
private ResultMode resultMode = DEFAULT_RESULT_MODE;
/** /**
* Initialize the request with a given path, and a requested number of facets * Constructor with the given category to aggregate and the number of child
* results. By default, all returned results would be labeled - to alter this * categories to return.
* default see {@link #setNumLabel(int)}.
* <p>
* <b>NOTE:</b> if <code>numResults</code> is given as
* <code>Integer.MAX_VALUE</code> than all the facet results would be
* returned, without any limit.
* <p>
* <b>NOTE:</b> it is assumed that the given {@link CategoryPath} is not
* modified after construction of this object. Otherwise, some things may not
* function properly, e.g. {@link #hashCode()}.
* *
* @throws IllegalArgumentException if numResults is &le; 0 * @param path
* the category to aggregate. Cannot be {@code null}.
* @param numResults
* the number of child categories to return. If set to
* {@code Integer.MAX_VALUE}, all immediate child categories will be
* returned. Must be greater than 0.
*/ */
public FacetRequest(CategoryPath path, int numResults) { public FacetRequest(CategoryPath path, int numResults) {
if (numResults <= 0) { if (numResults <= 0) {
@ -118,9 +116,6 @@ public abstract class FacetRequest {
categoryPath = path; categoryPath = path;
this.numResults = numResults; this.numResults = numResults;
numLabel = numResults; numLabel = numResults;
depth = DEFAULT_DEPTH;
sortOrder = SortOrder.DESCENDING;
hashCode = categoryPath.hashCode() ^ this.numResults; hashCode = categoryPath.hashCode() ^ this.numResults;
} }
@ -147,123 +142,125 @@ public abstract class FacetRequest {
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o instanceof FacetRequest) { if (o instanceof FacetRequest) {
FacetRequest that = (FacetRequest)o; FacetRequest that = (FacetRequest) o;
return that.hashCode == this.hashCode && return that.hashCode == this.hashCode &&
that.categoryPath.equals(this.categoryPath) && that.categoryPath.equals(this.categoryPath) &&
that.numResults == this.numResults && that.numResults == this.numResults &&
that.depth == this.depth && that.depth == this.depth &&
that.resultMode == this.resultMode && that.resultMode == this.resultMode &&
that.numLabel == this.numLabel; that.numLabel == this.numLabel &&
that.sortOrder == this.sortOrder;
} }
return false; return false;
} }
/** /**
* How deeply to look under the given category. If the depth is 0, * How deeply to look under {@link #categoryPath}. By default, only its
* only the category itself is counted. If the depth is 1, its immediate * immediate children are aggregated (depth=1). If set to
* children are also counted, and so on. If the depth is Integer.MAX_VALUE, * {@code Integer.MAX_VALUE}, the entire sub-tree of the category will be
* all the category's descendants are counted.<br> * aggregated.
* <p>
* <b>NOTE:</b> setting depth to 0 means that only the category itself should
* be aggregated. In that case, make sure to index the category with
* {@link OrdinalPolicy#ALL_PARENTS}, unless it is not the root category (the
* dimension), in which case {@link OrdinalPolicy#ALL_BUT_DIMENSION} is fine
* too.
*/ */
public final int getDepth() { public final int getDepth() {
// TODO add AUTO_EXPAND option // TODO an AUTO_EXPAND option could be useful
return depth; return depth;
} }
/** /**
* Returns the {@link FacetArraysSource} this {@link FacetRequest} uses in * Returns the {@link FacetArraysSource} this request uses in
* {@link #getValueOf(FacetArrays, int)}. * {@link #getValueOf(FacetArrays, int)}.
*/ */
public abstract FacetArraysSource getFacetArraysSource(); public abstract FacetArraysSource getFacetArraysSource();
/** /**
* If getNumLabel() &lt; getNumResults(), only the first getNumLabel() results * Allows to specify the number of categories to label. By default all
* will have their category paths calculated, and the rest will only be * returned categories are labeled.
* available as ordinals (category numbers) and will have null paths.
* <P>
* If Integer.MAX_VALUE is specified, all results are labled.
* <P>
* The purpose of this parameter is to avoid having to run the whole faceted
* search again when the user asks for more values for the facet; The
* application can ask (getNumResults()) for more values than it needs to
* show, but keep getNumLabel() only the number it wants to immediately show.
* The slow-down caused by finding more values is negligible, because the
* slowest part - finding the categories' paths, is avoided.
* <p> * <p>
* Depending on the {@link #getResultMode() LimitsMode}, this limit is applied * This allows an app to request a large number of results to return, while
* globally or per results node. In the global mode, if this limit is 3, only * labeling them on-demand (e.g. when the UI requests to show more
* 3 top results would be labeled. In the per-node mode, if this limit is 3, 3 * categories).
* top children of {@link #categoryPath the target category} would be labeled,
* as well as 3 top children of each of them, and so forth, until the depth
* defined by {@link #getDepth()}.
*
* @see #getResultMode()
*/ */
public final int getNumLabel() { public final int getNumLabel() {
return numLabel; return numLabel;
} }
/** Return the requested result mode. */ /** Return the requested result mode (defaults to {@link ResultMode#PER_NODE_IN_TREE}. */
public final ResultMode getResultMode() { public final ResultMode getResultMode() {
return resultMode; return resultMode;
} }
/** Return the requested order of results. */ /** Return the requested order of results (defaults to {@link SortOrder#DESCENDING}. */
public final SortOrder getSortOrder() { public final SortOrder getSortOrder() {
return sortOrder; return sortOrder;
} }
/** /**
* Return the value of a category used for facets computations for this * Return the weight of the requested category ordinal. A {@link FacetRequest}
* request. For a count request this would be the count for that facet, i.e. * is responsible for resolving the weight of a category given the
* an integer number. but for other requests this can be the result of a more * {@link FacetArrays} and {@link #getFacetArraysSource()}. E.g. a counting
* complex operation, and the result can be any double precision number. * request will probably return the value of the category from
* Having this method with a general name <b>value</b> which is double * {@link FacetArrays#getIntArray()} while an average-weighting request will
* precision allows to have more compact API and code for handling counts and * compute the value using both arrays.
* perhaps other requests (such as for associations) very similarly, and by
* the same code and API, avoiding code duplication.
* *
* @param arrays * @param arrays
* provider for facet arrays in use for current computation. * the arrays used to aggregate the categories weights.
* @param idx * @param ordinal
* an index into the count arrays now in effect in * the category ordinal for which to return the weight.
* <code>arrays</code>. E.g., for ordinal number <i>n</i>, with
* partition, of size <i>partitionSize</i>, now covering <i>n</i>,
* <code>getValueOf</code> would be invoked with <code>idx</code>
* being <i>n</i> % <i>partitionSize</i>.
*/ */
// TODO perhaps instead of getValueOf we can have a postProcess(FacetArrays) // TODO perhaps instead of getValueOf we can have a postProcess(FacetArrays)
// That, together with getFacetArraysSource should allow ResultHandlers to // That, together with getFacetArraysSource should allow ResultHandlers to
// efficiently obtain the values from the arrays directly // efficiently obtain the values from the arrays directly
public abstract double getValueOf(FacetArrays arrays, int idx); public abstract double getValueOf(FacetArrays arrays, int ordinal);
@Override @Override
public int hashCode() { public int hashCode() {
return hashCode; return hashCode;
} }
/**
* Sets the depth up to which to aggregate facets.
*
* @see #getDepth()
*/
public void setDepth(int depth) { public void setDepth(int depth) {
this.depth = depth; this.depth = depth;
} }
/**
* Sets the number of categories to label.
*
* @see #getNumLabel()
*/
public void setNumLabel(int numLabel) { public void setNumLabel(int numLabel) {
this.numLabel = numLabel; this.numLabel = numLabel;
} }
/** /**
* @param resultMode the resultMode to set * Sets the {@link ResultMode} for this request.
*
* @see #getResultMode() * @see #getResultMode()
*/ */
public void setResultMode(ResultMode resultMode) { public void setResultMode(ResultMode resultMode) {
this.resultMode = resultMode; this.resultMode = resultMode;
} }
/**
* Sets the {@link SortOrder} for this request.
*
* @see #getSortOrder()
*/
public void setSortOrder(SortOrder sortOrder) { public void setSortOrder(SortOrder sortOrder) {
this.sortOrder = sortOrder; this.sortOrder = sortOrder;
} }
@Override @Override
public String toString() { public String toString() {
return categoryPath.toString()+" nRes="+numResults+" nLbl="+numLabel; return categoryPath.toString() + " nRes=" + numResults + " nLbl=" + numLabel;
} }
} }