In the previous article in this series, we looked at how we can create a custom IA refiner with multiple mappings per refinement (using the out of the box “Result Type” refiner as an example).
In this article, we will take a look at a more complicated requirement where we only have a partially defined or confused IA (we will be creating custom refiner logic which can deal with multiple scenarios).
Please note: Throughout this article we will be referring to “Refiners” which refer to the whole refiner within the refiner Web Part control (screenshot taken from the previous article) and refinements / refinement items (e.g. Bid Report or Essentials and Help) as shown below:
We will be creating a custom refiner called “Workspace” which will meet the requirements of the scenario detailed below.
We will be looking at a more complex business scenario to explain how to put together the pieces of the puzzle:
Items which belong to one of the following site collections should be refinable with the relevant site name (e.g. News, Help etc..):
Items which belong to a site collection which start with the following should be grouped into the relevant refinement item and labelled appropriately (e.g. Essentials, Projects, Bids etc..):
Finally, the most complicated of the requirements is that items which belong to any one of the following, should be grouped into a single refinement item with the label Community:
The first thing we need to work out is what Managed Property is most suited for the refiner. The answer to this for our scenarios is the “SPSiteURL” managed property, which is the site URL for the artefact being returned in search. This property is great because it will aggregate content into site buckets for us, so we need to do less in our refiner. What’s not so great is that you cannot do a “contains” against this property, believe me I have tried.
To get around this property limitation we will use the “Path” managed property in the actual refinement, where we need to do a “contains” and not an “equals” match.
So in the code, we need to amend the item level display template to add the invoking code for our custom refiner logic. We do that by finding the catch all “else if” condition and amending the content as detailed below:
When the conditional logic states that we are processing our custom refiner it will invoke the function used to process the specific refinement in the loop and then update the array of refinements:
Where “Id” is the current index number in the refinements array (listData) and “Property” is the managed property we want to use for the actual refinement (this can be different to the managed property we have associated with the refiner). The “Type” parameter stipulates that we want to do a contains match (and not an “equals”).
Now we have the invoking code setup in the display template, we need to take care of the display template “wrap up tasks”.
Wrap up Tasks
Include the “Path” managed property in the refinements to clear when the “Show All” link is clicked:
Like we showed in the previous example we need to ensure that are refinements are done with an “Or” and not an “And” query. We can do this by amending the Item Level refiner display template and amend the if statement logic under the “addMethod” variable:
Custom Refiner Logic
Now we have all of the hooks in place to call our custom refiner, we need to build the thing. Taking the comments about modularisation from the previous article, I have added the custom logic into a separate centralised script.
First off all we create a name spaced function which contains the mappings for each of our scenarios detailed earlier in the article.
Once we have done that we need to create the helper methods for checking a “SPSiteURL” value against the appropriate array – to see if there is a match.
We will talk about these in detail a bit later when we get to the logic that uses them. In this next part, we will show the main guts of the refiner – the private and public functions (I have included detailed in-line comments):
It is possible to create a mapping using an in coming managed property, associated with a refiner (in the example above, we used “SPSiteURL”). If that managed property does not allow you to do what you need to do, you can use a different one for the actual refinement (in our case “Path”).
It is also possible to create mappings that cover the different scenarios you might have when trying to cover the different bases in the IA structure.
For the full example, take a look at the GIST below: