Search by facets, with Facet API + Hierarchical Select + Multiple selections.

June 18, 2021

A couple of days ago, we had to use facets with a field type Hierarchical Select which referred to a taxonomy of various levels. Up here, everything was fine, but the client also needed to select more than 2 elements of different levels ...

The settings was as follows:

  • Taxonomy Name: Colors, with the following terms:

    • Primary Colors
      • Red.
      • Yellow.
      • Blue.
    • Secondary Colors.
      • Violet.
      • Orange.
      • Green.
  • Field Type: Hierarchical Select, could not be configured to save the last element since the user could select a parent element and would have to obtained as a result all the children. Conclusion field must save the list of terms.

  • Facet could not be configured as OR, since the Hierarchical Select keeps a list of all parents to get to the end, this would cause that selecting term "Blue", the term parent also be selected, for thus also the red and yellow terms.

  • Facet could not be configured as AND, since the user needs to select more than two elements of the same or different parents.

The way to fix was in code, for this reason we invite you to read this post, where we will write about:

  1. Introduction to the facets.
  2. Basic configuration from the graphical interface.
  3. How altering facets from code using HOOK_facet_items_alter

To continue the post, we must have previously installed and configured Apache Solr Search, Search API and Facet API.

1. Introduction to the facets

One of the needs of the sites that have search for products or services offered (example Amazon) are builders to create and manage their search interfaces which must be clearly for users .

  • What are the faceted search? They are known as field-based criteria which are also used as filters in search pages, these facets can be any type of field, such as title, date, location searches and others...

2. Basic configuration from the graphical interface

  • How to enabled a facet? Go to Configuration menu - Search and Metadata - Search API, and proceed to select the indexer that is being used, within this we go to the edit option.

Indexer

We found five (5) tabs, View, edit, fields, filters and facets. Within the field tab, we will activate the Title field as seen in the image below.

Field

Once saved, we go to the tab facets within this field Title seekFacet

On the right side we see the options that have all fields facets, each of which shows different functions:

  • Configure Display: In this section you can select how the facet is displayed, Drupal by default brings us a couple of options

Display

  • Configure dependiencies: To set dependencies of these facets, either role, packet or other facets.
  • Configure Filters: It gives us the option to configure if we do not show some results exclude any of them, re-described based on a callback function, limit results based on minimal results or define the quantity of children to show.

3. How altering facets from code?

To perform this process, you must set the facet for it to be altered. Access the list of facets (admin/config/search/search_api), select the indexer to use and after click edit facets, once there look for the field to be modified and select edit filters facet. Once we ensure that the option to Rewrite facet items via callback function is selected.

Filters

The next step is to add the following hook in our module, in this example we get the markup results in uppercase.

 
function HOOK_facet_items_alter(&$build, &$settings) {
    if ($settings->facet == "YOUR_FACET_NAME") {
        foreach($build as $key => $item) {
            $build[$key]["#markup"] = drupal_strtoupper($item["#markup"]);
        }
    }
}
  • $ Settings -> Facet own settings.

Settings

  • $ Build -> Construction of the facet results.

Build

Validations to consider

  • For this example, the facet is configured as OR and Hierarchical Select field stores all items.

  • Into variable $build[$tid]['# query']['f'] are stored the filters, sample field_color:61 (which belongs to red color), this means that our quest to realize that value will as a filter, the red color.

  • When a child term is selected, the variable $build[$tid]['# query']['f'] by default add the filter father, continuing the above example, if we select the blue, we see that $build[$tid] ['# query']['f'] has field_color:61 and field_color: 60 (the father term, Primary Color), this means that we will have three filters, Red, Primary Colors and new color to select. Big problem because the filter by Primary Colors, also will filter red, blue and yellow.

  • To select more than 2 elements from different fathers, consider to be removed parents of both terms.

  • If a color is deselected example: When yellow deselect, verify if another color from the same father and the same hierarchy are selected, if so, we have 2 options.

    • If there are brothers terms selected should continue filtering on those.

    • If the term is deselected Finally, we need to pass new filter as the term parent for the user to keep searching.

Solution

This is a case to consider different validations to meet customer needs. The HOOK_facet_items_alter(&$build,&$settings) is very useful because it allows us to add or remove terms depending on the needs:

  • To remove a term.
     
    unset($build[$tid]['#query']['f'][$key_parent]);
    
  • To add a term(color blue for example, which tid os 63):
     
    $build[$tid]['#query']['f'][] = 'field_color:63';
    

Conclusion

Modules Apache Solr SearchSearch API and Facet API. They offer great flexibility to change/configure its properties, from the graphical user interface and the development of code. There are many sites which we can see results of such searches, pages from real estate sites selling products. Providing end users a convenient way to refine their searches.