[[facets]]
== Facets

Elasticsearch provides a full Java API to play with facets. See the
link:{ref}/search-facets.html[Facets guide].

Use the factory for facet builders (`FacetBuilders`) and add each facet
you want to compute when querying and add it to your search request:

[source,java]
--------------------------------------------------
SearchResponse sr = node.client().prepareSearch()
        .setQuery( /* your query */ )
        .addFacet( /* add a facet */ )
        .execute().actionGet();
--------------------------------------------------

Note that you can add more than one facet. See
link:{ref}/search-search.html[Search Java API] for details.

To build facet requests, use `FacetBuilders` helpers. Just import them
in your class:

[source,java]
--------------------------------------------------
import org.elasticsearch.search.facet.FacetBuilders.*;
--------------------------------------------------

[float]
=== Facets

[float]
==== Terms Facet

Here is how you can use
link:{ref}/search-facets-terms-facet.html[Terms Facet]
with Java API.

[float]
===== Prepare facet request

Here is an example on how to create the facet request:

[source,java]
--------------------------------------------------
FacetBuilders.termsFacet("f")
    .field("brand")
    .size(10);
--------------------------------------------------

[float]
===== Use facet response

Import Facet definition classes:

[source,java]
--------------------------------------------------
import org.elasticsearch.search.facet.terms.*;
--------------------------------------------------

[source,java]
--------------------------------------------------
// sr is here your SearchResponse object
TermsFacet f = (TermsFacet) sr.facets().facetsAsMap().get("f");

f.getTotalCount();      // Total terms doc count
f.getOtherCount();      // Not shown terms doc count
f.getMissingCount();    // Without term doc count

// For each entry
for (TermsFacet.Entry entry : f) {
    entry.getTerm();    // Term
    entry.getCount();   // Doc count
}
--------------------------------------------------

[float]
==== Range Facet

Here is how you can use
link:{ref}/search-facets-range-facet.html[Range Facet]
with Java API.

[float]
===== Prepare facet request

Here is an example on how to create the facet request:

[source,java]
--------------------------------------------------
FacetBuilders.rangeFacet("f")
    .field("price")         // Field to compute on
    .addUnboundedFrom(3)    // from -infinity to 3 (excluded)
    .addRange(3, 6)         // from 3 to 6 (excluded)
    .addUnboundedTo(6);     // from 6 to +infinity
--------------------------------------------------

[float]
===== Use facet response

Import Facet definition classes:

[source,java]
--------------------------------------------------
import org.elasticsearch.search.facet.range.*;
--------------------------------------------------

[source,java]
--------------------------------------------------
// sr is here your SearchResponse object
RangeFacet f = (RangeFacet) sr.facets().facetsAsMap().get("f");

// For each entry
for (RangeFacet.Entry entry : f) {
    entry.getFrom();    // Range from requested
    entry.getTo();      // Range to requested
    entry.getCount();   // Doc count
    entry.getMin();     // Min value
    entry.getMax();     // Max value
    entry.getMean();    // Mean
    entry.getTotal();   // Sum of values
}
--------------------------------------------------

[float]
==== Histogram Facet

Here is how you can use
link:{ref}/search-facets-histogram-facet.html[Histogram
Facet] with Java API.

[float]
===== Prepare facet request

Here is an example on how to create the facet request:

[source,java]
--------------------------------------------------
HistogramFacetBuilder facet = FacetBuilders.histogramFacet("f")
    .field("price")
    .interval(1);
--------------------------------------------------

[float]
===== Use facet response

Import Facet definition classes:

[source,java]
--------------------------------------------------
import org.elasticsearch.search.facet.histogram.*;
--------------------------------------------------

[source,java]
--------------------------------------------------
// sr is here your SearchResponse object
HistogramFacet f = (HistogramFacet) sr.facets().facetsAsMap().get("f");

// For each entry
for (HistogramFacet.Entry entry : f) {
    entry.getKey();     // Key (X-Axis)
    entry.getCount();   // Doc count (Y-Axis)
}
--------------------------------------------------

[float]
==== Date Histogram Facet

Here is how you can use
link:{ref}/search-facets-date-histogram-facet.html[Date
Histogram Facet] with Java API.

[float]
===== Prepare facet request

Here is an example on how to create the facet request:

[source,java]
--------------------------------------------------
FacetBuilders.dateHistogramFacet("f")
    .field("date")      // Your date field
    .interval("year");  // You can also use "quarter", "month", "week", "day",
                        // "hour" and "minute" or notation like "1.5h" or "2w"
--------------------------------------------------

[float]
===== Use facet response

Import Facet definition classes:

[source,java]
--------------------------------------------------
import org.elasticsearch.search.facet.datehistogram.*;
--------------------------------------------------

[source,java]
--------------------------------------------------
// sr is here your SearchResponse object
DateHistogramFacet f = (DateHistogramFacet) sr.facets().facetsAsMap().get("f");

// For each entry
for (DateHistogramFacet.Entry entry : f) {
    entry.getTime();    // Date in ms since epoch (X-Axis)
    entry.getCount();   // Doc count (Y-Axis)
}
--------------------------------------------------

[float]
==== Filter Facet (not facet filter)

Here is how you can use
link:{ref}/search-facets-filter-facet.html[Filter Facet]
with Java API.

If you are looking on how to apply a filter to a facet, have a look at
link:#facet-filter[facet filter] using Java API.

[float]
===== Prepare facet request

Here is an example on how to create the facet request:

[source,java]
--------------------------------------------------
FacetBuilders.filterFacet("f",
    FilterBuilders.termFilter("brand", "heineken"));    // Your Filter here
--------------------------------------------------

See <<query-dsl-filters,Filters>> to
learn how to build filters using Java.

[float]
===== Use facet response

Import Facet definition classes:

[source,java]
--------------------------------------------------
import org.elasticsearch.search.facet.filter.*;
--------------------------------------------------

[source,java]
--------------------------------------------------
// sr is here your SearchResponse object
FilterFacet f = (FilterFacet) sr.facets().facetsAsMap().get("f");

f.getCount();   // Number of docs that matched
--------------------------------------------------

[float]
==== Query Facet

Here is how you can use
link:{ref}/search-facets-query-facet.html[Query Facet]
with Java API.

[float]
===== Prepare facet request

Here is an example on how to create the facet request:

[source,java]
--------------------------------------------------
FacetBuilders.queryFacet("f",
    QueryBuilders.matchQuery("brand", "heineken"));
--------------------------------------------------

[float]
===== Use facet response

Import Facet definition classes:

[source,java]
--------------------------------------------------
import org.elasticsearch.search.facet.query.*;
--------------------------------------------------

[source,java]
--------------------------------------------------
// sr is here your SearchResponse object
QueryFacet f = (QueryFacet) sr.facets().facetsAsMap().get("f");

f.getCount();   // Number of docs that matched
--------------------------------------------------

See <<query-dsl-queries,Queries>> to
learn how to build queries using Java.

[float]
==== Statistical

Here is how you can use
link:{ref}/search-facets-statistical-facet.html[Statistical
Facet] with Java API.

[float]
===== Prepare facet request

Here is an example on how to create the facet request:

[source,java]
--------------------------------------------------
FacetBuilders.statisticalFacet("f")
   .field("price");
--------------------------------------------------

[float]
===== Use facet response

Import Facet definition classes:

[source,java]
--------------------------------------------------
import org.elasticsearch.search.facet.statistical.*;
--------------------------------------------------

[source,java]
--------------------------------------------------
// sr is here your SearchResponse object
StatisticalFacet f = (StatisticalFacet) sr.facets().facetsAsMap().get("f");

f.getCount();           // Doc count
f.getMin();             // Min value
f.getMax();             // Max value
f.getMean();            // Mean
f.getTotal();           // Sum of values
f.getStdDeviation();    // Standard Deviation
f.getSumOfSquares();    // Sum of Squares
f.getVariance();        // Variance
--------------------------------------------------

[float]
==== Terms Stats Facet

Here is how you can use
link:{ref}/search-facets-terms-stats-facet.html[Terms
Stats Facet] with Java API.

[float]
===== Prepare facet request

Here is an example on how to create the facet request:

[source,java]
--------------------------------------------------
FacetBuilders.termsStatsFacet("f")
    .keyField("brand")
    .valueField("price");
--------------------------------------------------

[float]
===== Use facet response

Import Facet definition classes:

[source,java]
--------------------------------------------------
import org.elasticsearch.search.facet.termsstats.*;
--------------------------------------------------

[source,java]
--------------------------------------------------
// sr is here your SearchResponse object
TermsStatsFacet f = (TermsStatsFacet) sr.facets().facetsAsMap().get("f");
f.getTotalCount();      // Total terms doc count
f.getOtherCount();      // Not shown terms doc count
f.getMissingCount();    // Without term doc count

// For each entry
for (TermsStatsFacet.Entry entry : f) {
    entry.getTerm();            // Term
    entry.getCount();           // Doc count
    entry.getMin();             // Min value
    entry.getMax();             // Max value
    entry.getMean();            // Mean
    entry.getTotal();           // Sum of values
}
--------------------------------------------------

[float]
==== Geo Distance Facet

Here is how you can use
link:{ref}/search-facets-geo-distance-facet.html[Geo
Distance Facet] with Java API.

[float]
===== Prepare facet request

Here is an example on how to create the facet request:

[source,java]
--------------------------------------------------
FacetBuilders.geoDistanceFacet("f")
    .field("pin.location")              // Field containing coordinates we want to compare with
    .point(40, -70)                     // Point from where we start (0)
    .addUnboundedFrom(10)               // 0 to 10 km (excluded)
    .addRange(10, 20)                   // 10 to 20 km (excluded)
    .addRange(20, 100)                  // 20 to 100 km (excluded)
    .addUnboundedTo(100)                // from 100 km to infinity (and beyond ;-) )
    .unit(DistanceUnit.KILOMETERS);     // All distances are in kilometers. Can be MILES
--------------------------------------------------

[float]
===== Use facet response

Import Facet definition classes:

[source,java]
--------------------------------------------------
import org.elasticsearch.search.facet.geodistance.*;
--------------------------------------------------

[source,java]
--------------------------------------------------
// sr is here your SearchResponse object
GeoDistanceFacet f = (GeoDistanceFacet) sr.facets().facetsAsMap().get("f");

// For each entry
for (GeoDistanceFacet.Entry entry : f) {
    entry.getFrom();            // Distance from requested
    entry.getTo();              // Distance to requested
    entry.getCount();           // Doc count
    entry.getMin();             // Min value
    entry.getMax();             // Max value
    entry.getTotal();           // Sum of values
    entry.getMean();            // Mean
}
--------------------------------------------------

[float]
=== Facet filters (not Filter Facet)

By default, facets are applied on the query resultset whatever filters
exists or are.

If you need to compute facets with the same filters or even with other
filters, you can add the filter to any facet using
`AbstractFacetBuilder#facetFilter(FilterBuilder)` method:

[source,java]
--------------------------------------------------
FacetBuilders
    .termsFacet("f").field("brand") // Your facet
    .facetFilter( // Your filter here
        FilterBuilders.termFilter("colour", "pale")
    );
--------------------------------------------------

For example, you can reuse the same filter you created for your query:

[source,java]
--------------------------------------------------
// A common filter
FilterBuilder filter = FilterBuilders.termFilter("colour", "pale");

TermsFacetBuilder facet = FacetBuilders.termsFacet("f")
    .field("brand")
    .facetFilter(filter);                           // We apply it to the facet

SearchResponse sr = node.client().prepareSearch()
    .setQuery(QueryBuilders.matchAllQuery())
    .setFilter(filter)                              // We apply it to the query
    .addFacet(facet)
    .execute().actionGet();
--------------------------------------------------

See documentation on how to build
<<query-dsl-filters,Filters>>.

[float]
=== Scope

By default, facets are computed within the query resultset. But, you can
compute facets from all documents in the index whatever the query is,
using `global` parameter:

[source,java]
--------------------------------------------------
TermsFacetBuilder facet = FacetBuilders.termsFacet("f")
    .field("brand")
    .global(true);
--------------------------------------------------
