Faceted Navigation with Hippo CMS and HST2


Categorizing and presenting large volumes of documents is a big challenge. Content can be organized by a combination of three different models — Using Hierarchies (organized into folders), Using Categories (attaching taxonomy category to a document) or by Using Tags. These three organization models can serve as navigational models for the content as well.

When the content size grows larger these models hinder the accessibility of the content. This also affects the discoverability of the content, of course searching is an option but search itself cannot be considered as navigation since the users needs to be aware of what properties the content has and how to specify the criteria. Faceted Navigation solves this problem by providing a way to access the in series of refining queries. The users can drill down and access the content the way they want. Hippo CMS, along with HST provides excellent support for creating a faceted navigation of your content. In this article I’ll try to explain how you can build your own faceted navigation in your website using Hippo CMS and Hippo Site Toolkit.

Faceted Navigation

Faceted Navigation allows the user to navigate through the content by a series of refined queries on the metadata. The main benefit of having a faceted navigation than a rigid hierarchical navigation is that the user navigate the content in multiple paths, thus saving the time for reaching the content.

Faceted Classification : History

The Colon Classification was the first faceted classification implementation, which was developed by a noted Indian mathematician and librarian S.R.Ranganathan. Ranganathan was also famous for his Five Laws of Library Science:

  1. Books are for use.
  2. Every reader his [or her] book.
  3. Every book its reader.
  4. Save the time of the reader.
  5. The library is a growing organism.

which I think can be applied not only to books but for any knowledge entities.

Faceted Navigation in Hippo Repository is built on top of document node’s properties. As you might already know Hippo CMS is a JCR (Java Content Repository) based. Each node( or document) will have various properties (or fields) in which the data is saved. To design effective faceted navigation you may want to make sure that you don’t have any implicit metadata in the structure of the content. Suppose that you have a blog with posts that belong to various categories. You should put the category name as a field in the document rather than organizing the posts into a category folder hierarchy.

Configuring Faceted Navigation in Repository

Before we delve into creating faceted navigtion, let me explain the example scenario we are going to use for this article.

Imagine you are building a website for an online game shop which sells games for computers and digital gaming consoles likee XBOX, Wii, Play Station. The repository contains documents which represent a game. The node type definition for the product is shown below:

[myshop:games] > myshop:basedocument
- myshop:title       (string)
+ myshop:description (hippostd:html)
- myshop:date        (string)
- myshop:price       (double)
- myshop:tags        (string) multiple
- myshop:genres      (string) multiple < 'Action', 'Adventure', 'Aracade', 'Board'
- myshop:consoles    (string) multiple< 'XBOX 360', 'Wii', 'Play Station', 'PC', 'Mac'

In the following I used the default content of the Hippo CMS, so the namespace of the nodes will be defaultcontent rather than myshop. In your case, it will the name you use for your project

You can create the document using the CMS template builder. For the sake of simplicity I defined the genres as a multivalued property. You can of course use some advanced way of classifying the content, e.g., using Hippo Taxonomy plugin, to categorize it properly.The properties (or fields) of the game document are self-descriptive. All the game documents are saved under the folder /content/documents/myshop/games.

Game Document & Template

Before creating any facet navigation nodes, make sure you have some content. Create a few documents in a folder called games with different values so that we can test our facets.

Simple Faceted Navigation

Let us start by a simple use case of building a faceted navigation for the games by consoles. You can configure the faceted navigation node in the repository by creating a node of the type hippofacnav:facetnavigation. The facetnavigation nodes can be created anywhere in the content tree, but the ideal place for them would be under the content/documents/{your_project}. In this way you can access the entire faceted navigation tree using the HST and display them in your website.

First open the CMS console and navigate to /content/documents/{your_project} node. Create a new node of the type hippofacnav:facetnavigation and name it games_by_console. We want to display the list of game documents under the games folder. Take a note of the UUID of the games folder. Add a new string property with name hippo:docbase and give the UUID of the games folder as the value for the property. Now add a multi-values string property with name hippofacnav:facets. Facet is the property based on which we want to provide a dimension to the facet navigation. Since we want to have a list of documents based on consoles, add the value for the facets property as {project_namespace}:consoles. In my example the property name is defaultcontent:consoles. On reloading the tree your facetnavigation node should show the results as shown below:

Games by Console

Facets with Ranges

Specifying the range for a facet value is very easy. Let us create a navigation based on price range. First create a new hippofacnav:facetnavigation and name it games_by_price_range. Add the hippo:docbase property similar to the previous example and specify the hippofacnav:facets property with value defaultcontent:price. Alternatively, you can just copy the games-by-consoles node and rename it accordingly. When you refresh the node it will have the result of the facet already populated as shown below:

Games by Price

You can specify a range of the facet/property value using JSON notation. Each of the range specifier will be similar to an object in JSON and they are wrapped into an array. To create a price range facet, replace the defaultcontent:price with

defaultcontent:price$[{name:'less 20.00', resolution:'double', end:20.00}]

Also to make the tree more readable add the hippofacnav:facetnodenames with value price. Now if you reload the tree you can see the documents that have the price range as specified.

Games by Price Range

You can add more ranges as shown below:

                {name:'less 20.00', resolution:'double', end:20.00},
                {name: '20.00 - 30.00', resolution:'double', begin:20.00, end:30.00},
                {name:'more than 30.00', resolution:'double', begin:30.00}

The resolution can be one of ‘long’, ‘double’, ‘year’, ‘month’, ‘week’, ‘day’, ‘hour’ or ‘string’. The begin of the range is inclusive and the end is exclusive. So when you specify begin:1,end:5 for a facet it is equivalent to [1,5). More information about the ranges is available on the Hippo Wiki.

Guided Navigation and Multiple Facets

When you add multiple facets to a node, the resulting documents will show all the facets again. When you want to display the same navigational nodes in the website then this can be quite annoying for the user. To eliminate this problem you can configure the facets to be hidden and specify the order in which they are visible.

Before setting hide property

Console Before Hide

First modify the games-by-console by adding another facet value defaultcontent:genres. Now if you reload the tree below you’ll find that under each value of console the facet consoles is repeated again. Now just replace the facetnodename value of the consoles by ${hide:’consoles’} you can hide the genres using similar approach. After the hide property is added, the nodes will look like this:

After setting hide property

Consoles After Hide

Using the same approach you can hide and show the different facets essentially creating a guided navigation for the user.

Sorting and limiting the facet results

To sort the result set of a facet you can use the sortby and sortorder for a facetnodename. To sort the game documents displayed under price range by increasing order of prices you can use the following code:

        price${sortby:'facetvalue', sortorder:'descending'}

The limit can be specified by using count as the sortby and setting limit to the desired value.

        price${sortby:'count', limit:2}

If you specify the limit the result set will still show the complete result, but the facet node’s child node will only show 2 result nodes.

There are many more options you can specify in Faceted Navigation nodes, check the Wiki Page for more information.

Faceted Navigation in Website

So far we created the navagation completely in the repository. From the website perspective the facet result nodes are just regular mirror nodes. So you can fetch the data and display the nodes accordingly in your website. Another important thing to note is that the faceted navigation nodes respect the live and preview mode. So you don’t need to worry about whether unpublished documents being visible in the live website. HST also provides a utility tag facetnavigationlink that can generate a link to a Tag.

To see the Facet Navigation in action, you can always checkout the Demo Suite from HST Subversion repository. Also you can see the facet navigation in @jashaj‘s blog posts page.

Of course, you are always welcome to ask questions on our mailing lists or send us feedback via feedback forum. Stay tuned for more In-depth articles about Hippo product suite.

One thought on “Faceted Navigation with Hippo CMS and HST2

  1. Tweets that mention VijayKiran.com » Building Faceted Navigation with Hippo CMS & HST2 -- Topsy.com

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>