Faceted Searching

Prices, Manufacturers and Categories

Whenever products are returned through the KonaKart API, attributes in the ProductSearch object can be set so that the result contains a list of Price, Manufacturer and Category facets, all of which contain information regarding the number of products available per facet. For Manufacturer and Category facets the ProductSearch object contains a boolean that must be set to true. In order to return price facets a PriceFacetOptions object must be instantiated and attached to the ProductSearch object. The PriceFacetOptions object defines how the facets are generated by specifying the facet size, start price and end price. There is a configuration variable for the storefront application that determines whether price facets or a price slider is displayed to allow the customer to filter the search by price. The default behaviour is to display the slider.

Custom Faceted Search

KonaKart allows a configurable way to use the powerful faceted search functionality of Solr by allowing different facets to be defined for different product types. An example will be used in order to demonstrate how to use the Administration Application to configure product attributes to be used as facets.

The example uses the standard KonaKart demonstration database which contains three DVD products under the DVD Movies >> Drama category. The first step is to define a set of custom attributes which can be applied to DVDs and can be used to return facet values.

Define Custom Attributes

As can be seen from the image, each attribute is assigned a facet number (from 1 to 30) which is used to map that attribute to a facet field in the Solr schema. In this particular example, since the custom attributes can only take a fixed number of values, a drop list is defined (in the Set Function field) containing the allowed values. Once the custom attributes have been defined, a custom attribute template must be created to group the new attributes:

Define Custom Attribute Template

Once the template has been inserted, the three custom attributes may be added to the template by clicking on the Attributes button. The next step is to select each of the products within the Drama category:

Select Products in Drama Category

As shown below, each product within the Drama category must be associated with the DVD template created earlier.

Add template to product

Once the template has been added to the product, the values of the new custom attributes may be set by selecting allowed values from the drop lists and clicking the Save button.

Set custom attribute values

At this point, we've completed the setup procedure for products. Now what needs to be done is to create three Tag Groups (one for each custom attribute) mapped to the same facet numbers as the custom attributes.

Create tag groups

As can be seen from the above image, the Rating Tag Group is mapped to facet number 2 which is the same as the Rating custom attribute. This mapping also applies to the Genre and Type Tag Groups. Once the Tag Groups have been inserted they must be associated to the Drama Category as can be seen below. The order is important this will be the order in which they are read using the KonaKart API.

Add tag groups to category

The reasons for creating a Tag Group for each facet field are twofold. Within KonaKart, Solr faceted search may only be used if a category id is specified in the search query. A category id is mandatory because only similar products belonging to the same category and associated with the same template must be returned. If a DVD and another type of product such as a Keyboard were returned in the same query, it would be impossible to have a set of facets applicable to both products. When a customer clicks on a category in the storefront application, the code must retrieve the Tag Groups associated with that category and pass these to the Product Search API call. Using this information, the KonaKart engine code can determine the sort order for the returned facet data (i.e. the same as the sort order of the Tag Groups) and if Solr doesn't return any data for one or more facets, the API call still returns the facet value with no entries so that it may be displayed on the UI.

Before testing the configuration with some API calls, the products must be added to Solr as shown below:

Add products to Solr

The next part of this tutorial will demonstrate how the KonaKart Engine API may be used to retrieve products in the Drama Category using queries that return facet information and how to add the facet information as a constraint.


            /*
             * Get the tag groups for the Drama Category
             */
            TagGroupIf[] groups = eng.getTagGroupsPerCategory(dramaCatId,/* getProdCount */false,
                    KKConstants.DEFAULT_LANGUAGE_ID);

            /*
             * Create a ProductSearch object for the search
             */
            ProductSearch search = new ProductSearch();
            search.setReturnCustomFacets(true);
            search.setCategoryId(dramaCatId);
            search.setTagGroups(groups);

            ProductsIf prods = eng.searchForProducts(null, null, search, DEFAULT_LANGUAGE);

            for (int i = 0; i < prods.getCustomFacets().length; i++)
            {
                KKFacetIf facet = prods.getCustomFacets()[i];

                System.out.println(facet.getName() + " - " + facet.getNumber());
                if (facet.getValues() != null)
                {
                    for (int j = 0; j < facet.getValues().length; j++)
                    {
                        NameNumberIf value = facet.getValues()[j];
                        System.out.println("\t" + value.getName() + "(" + value.getNumber() + ")");
                    }
                }
            }

The above code retrieves the Tag Groups for the category. It then creates a ProductSearch object, passing it the Tag Groups, the Category Id and instructions to return custom facets. The print out from running the code can be seen below:


Rating - 2
	G(1)
	PG(1)
	R(1)
Type - 3
	Blu-ray(2)
	HD-DVD(1)
Genre - 1
	drama(3)
	

This is what we would expect because the products have been set up like this:

  • Product1: Rating = PG, Type = Blu-ray, Genre = drama

  • Product2: Rating = G, Type = Blu-ray, Genre = drama

  • Product3: Rating = R, Type = HD-DVD, Genre = drama

We can pass a constraint to the search by adding it to the relevant Product Group as shown below. The constraint is that the rating must be "R". Note that Rating is the first Tag Group in the list.


            /*
             * Get the tag groups for the Drama Category
             */
            TagGroupIf[] groups = eng.getTagGroupsPerCategory(dramaCatId,/* getProdCount */false,
                    KKConstants.DEFAULT_LANGUAGE_ID);

            /*
             * Create a ProductSearch object for the search
             */
            ProductSearch search = new ProductSearch();
            search.setReturnCustomFacets(true);
            search.setCategoryId(dramaCatId);
            groups[0].setFacetConstraint("R"); // The first tag group is Rating
            search.setTagGroups(groups);

            ProductsIf prods = eng.searchForProducts(null, null, search, DEFAULT_LANGUAGE);

            for (int i = 0; i < prods.getCustomFacets().length; i++)
            {
                KKFacetIf facet = prods.getCustomFacets()[i];

                System.out.println(facet.getName() + " - " + facet.getNumber());
                if (facet.getValues() != null)
                {
                    for (int j = 0; j < facet.getValues().length; j++)
                    {
                        NameNumberIf value = facet.getValues()[j];
                        System.out.println("\t" + value.getName() + "(" + value.getNumber() + ")");
                    }
                }
            }

This constraints forces KonaKart to return only one product as can be seen from the print out:


Rating - 2
	R(1)
Type - 3
	HD-DVD(1)
Genre - 1
	drama(1)
	

Multi-Valued Facets

In some cases it is convenient to display a facet such as color, which may have multiple values for the same product. For example a shirt may come in blue and red but not yellow. The instructions for setting up this type of facet are as follows.

1) For each color create a custom attribute:

The Set Function should be entered as shown in the image above option(yellow=yes,=no) so that only one value is created to select all yellow shirts and not all non-yellow shirts. For multi-lingual web sites you should substitute the word "yellow" with a message catalog key.

2) For each color create a Tag Group with the same facet number as the color:

Ensure that the name of each tag group is identical as shown above where they have all been called Color (highlighted in yellow).

3) Associate the tag group to the category that contains the products.

4) Add all colors to a Custom Attribute Template and add this template to a product so that the values may be edited from the edit product panel as shown below.

In the storefront application the color facets will be displayed as shown below:

The JSP that displays the facets (Facets.jsp) loops through all of the tag groups for the category but only creates a new heading if the next tag group has a different name to the previous tag group. This is why it is important for all tag groups to have the same name.