Search code examples
elasticsearchfaceted-search

Efficient way to compute *Facet Counts* in Elastic Search


I want to compute facet counts for a facet query UI but I think I am missing something as I am unable to get the numbers I need using facet filters.

Here's an example. Given two facets with three possible terms in each facet:

Colors: {red, yellow, blue}
Notes: {do, re, mi}

When I do a search, the counts for each term in a facet do not take into account the filters set in the other facet.

To illustrate:

[ ] All colors (18)
 [x] Red (10)
 [ ] Green (5)
 [ ] Blue (3)

[ ] All notes (18)
 [ ] Do (5)
 [x] Re (7)
 [ ] Mi (6)

Note that the totals within each facet sum to the total number of hits for the query as though no filters are set.

The behaviour I want is for the numbers in the Notes facet to take into account the filter in the Colors facet and vice versa. That is, the numbers for the note terms should sum to 10 (to match the red filter), not 18.

Interestingly, the example screenshot in the docs uses an example from Linked In which actually demonstrates the behavior that I want.

http://www.elasticsearch.org/guide/reference/api/search/facets/

I am able to get the result I want by manually resubmitting the query once for each term in each facet (ugh) but I wonder if there is a way to get the same behaviour as LinkedIn out of the box by changing my query.


Solution

  • The only way I've found this to work is via the following logic for any multi-select facet:

    Whenever the user selects a value from a facet ("drills down") you add a corresponding filter to all facets (via facet_filter) except the facet that the selection was done in, as well as to the top-level filter to filter the query results.

    In other words, given 3 multi-select facets, A, B & C:

    • Select value from A => Add filter to top-level filter as well as to the facet_filter of facet B and C.
    • Select value from B => Add filter to top-level filter as well as to the facet_filter of A & C.
    • ... and so on

    The top-level filter always combines the filters for all selections, whereas each individual facet contains facet_filters according to the selection in the other facets.