Displaying faceted navigation

Displaying facets using a Funnelback template

When using a Funnelback template, the display of faceted navigation in the search interface is controlled by the Freemarker search template.

The default Freemarker template includes the required template code for displaying faceted navigation. If you create any new templates based on this, faceted navigation will work correctly with minimal changes within the template.

If you have upgraded from a previous version of Funnelback and use a Funnelback template to display faceted navigation, you will need to upgrade your template and convert your facets in order to make use of the new facet types. The old faceted navigation macros, <@s.FacetedSearch> and any other facet macro tags nested within were removed from Funnelback in v16.0.

If you integrate directly with the data model you will need to update your integration to ensure you don’t access the categories node beneath response.facets as this has been removed, and we also recommend upgrading your faceted navigation configuration to be a non-legacy facet type.

To upgrade your template and faceted navigation configuration please see the upgrading legacy facets guide.

Controlling what facets are shown and the facet display order

The order in which facets appear in Funnelback Freemarker templates is determined by the order in which they appear in the configuration, and this is based on the order in which they were modified.

The default template will display the facets in this order using the following iterator:

<#list response.facets as facet>

This can be replaced with a call to the getFacets method. This allows control from within the template of both the facet display order, and the facets to display.

e.g. to display three facets named Author, Location and Type in that order using the following:

<#list getFacets(response,  ["Author", "Location", "Type"]) as facet>
the facet names must exactly match the names used when configuring the facet and are case-sensitive.

Other facets that exist for the frontend service will not be displayed when using getFacets.

Increasing the number of category values returned by the query processor

By default Funnelback will return up to 100 categories for each metadata field that is used for faceted navigation.

This can be increased by setting the rmc_maxperfield query processor option in the results page configuration. Increasing the value could impact performance, especially on collections that have large numbers of metadata values for the fields being counted.

e.g. Return a maximum of 150 categories per facet. Add the following option to the query_processor_options in the results page configuration:

Parameter key Value

query_processor_options

-rmc_maxperfield=150

Preserving facet constraints between searches

The search box supports a parameter that will preserve any applied facets when a new search is submitted.

This parameter, facetScope, is a CGI parameter that passes through the currently set facets so that they are maintained when the other search constraints (such as the query terms) are changed.

The facetscope is usually rendered as a checkbox that appears within the search box when any facets are selected by calling the FacetScope macro from the Funnelback classic macro library.

<@s.FacetScope> Within selected categories only</@s.FacetScope>

See: FacetScope macro definition for information on how the facetScope parameter value is constructed if you wish to implement this in a search that integrated directly with the data model.

Reading faceted navigation from the data model

Faceted navigation information is available as JSON or XML via the search.xml and search.json endpoints.

Faceted navigation data model object

The faceted navigation data is available under response.facets in the search response. This contains a list of facets. For display purposes the following fields are useful:

  • name: The name of the facet for example Authors.

  • unselectAllUrl: The URL parameters required to unselect the facet. For example this might contain ?query=foo.

  • guessedDisplayType: Gives the UI an idea of how to display the facet. Possible values are:

    • SINGLE_DRILL_DOWN: This is used for nested facets for example when drilling down to a location you may have selected Australia then New South Wales and you may be presented with a list of unselected category values consisting of cities or regions within NSW.

    • CHECKBOX: The category values should be shown as check boxes where multiple category values can be selected at a time.

    • RADIO_BUTTON: The category values should be shown as radio buttons where only one category value can be selected at a time.

    • TAB: The category value should be shown as a tab typically at the top of the page.

    • UNKNOWN: The facet has been configured in an unknown way and so the developer must decide how to display the category values.

  • allValues: Contains all category values which should be shown to the user in the configured order.

  • selectedValues: Contains all of the category values that have been selected, this is useful for displaying breadcrumbs.

The category value contains the following useful fields for displaying facets:

  • label: The display label of the category value that should be shown to the user. For example: "Bob", "Last year", "High Distinction".

  • count: The expected number of matching documents should this category value be selected. Note can be null when the value could not be calculated.

  • selected: A boolean (true/false) showing if the category value is selected.

  • toggleUrl: The URL parameters required to change the selected state of the category value. If the category value was selected this would unselect the category value. An example of what this might contain is ?query=foo&f.Bar=foo.

Displaying the model.

If you are implementing code to handle facets you may want to see displaying facets using a Funnelback template and also look at the Freemarker code used to iterate over and render the facets as shown in the upgrading legacy facets guide.

Example pseudo code on how to display the model is presented below. It will show RADIO_BUTTON, CHECKBOX and SINGLE_DRILL_DOWN facets.

for(facet in response.facets) {
  // Show a link to unselect this facet.
  if(facet.selected) {
    print <a href="${facet.unselectAllUrl}">❌  clear all: </a>
  }

  // Loop over all category values and show them to the user in the configured order.
  for(categoryValue in facet.allValues) {
    // Show a clickable link if the categoryValue is selected or if clicking the link would
    // result in more than zero documents.
    boolean showLink = categoryValue.selected || categoryValue.count == null || categoryValue.count > 0;
    if(showLink) {
      print <a href="${value.toggleUrl}>"
    }

    // Work out what we want to show to the user for example 🔘 Bob or, ❌ Bob
    if(facet.guessedDisplayType == "RADIO_BUTTON") {
      if(categoryValue.selected) {
        print  🔘
      } else {
        print  ⃝
      }
    } else if(facet.guessedDisplayType == "CHECKBOX") {
      if(categoryValue.selected) {
        print  ☑
      } else {
        print ☐
      }
    } else if(categoryValue.selected){
      print ❌
    }

    // Show the label
    print categoryValue.label

    if(showLink) {
      print </a>
    }

    if(categoryValue.count != null) {
      print categoryValue.count
    }

    // Show a arrow down for drill down facets.
    if(facet.guessedDisplayType == "SINGLE_DRILL_DOWN" && categoryValue.selected && haveMoreValuesToShow) {
          print ↓
    }
  }
}

Other things to consider when presenting facets:

  • Provide allowance for controlling the order in which facets are displayed.

  • Exclude TAB type facets when presenting the main list of facets.

  • Provide allowance to handle the maximum number of category values to show to the user. Some facets may return tens or hundreds of category values.