Thursday, October 17, 2013

SharePoint 2013 Search: Changing Refinements from 'OR' to 'AND'

By default when you implement refiners in SharePoint 2013 Search, the search experience when selecting the multi-value refinements, the filtering of the search results follows "OR" logic. If you selected SharePoint and Visio, for example, the results will display all items that either contain SharePoint or contain Visio (or both). In some cases, the user may want to combine the values such that only items that contain both SharePoint and Visio are displayed.

I started looking into this within the refinement filter code but also asked two SharePoint buddies that have been working with refinements recently if they saw a way to do this. They both came up with the same solution.

The first response and more detailed solution came from CCDW.

Here is the solution (based on modifying the system function in place) - the right way to implement this is discussed after the initial discovery:

PART I - Javascript Function

Step 1:  Locate the Search.ClientControls.js file in C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\template\layouts.

Step 2: Open the debug version of this file and locate the following line:

Srch.Refinement.submitMultiRefinement = function Srch_Refinement$submitMultiRefinement(name, control, useContains, useKQL) {

and change to:

Srch.Refinement.submitMultiRefinement = function Srch_Refinement$submitMultiRefinement(name, control, useContains, useKQL, searchBoolean) {

Here we are adding a fifth parameter named searchBoolean which we will use to pass in AND or OR

Step 3: Check  to see if the parameter was passed.

Add this line in the function:

searchBoolean = searchBoolean || 'OR';

If the parameter is not passed, we set it to the original default value such that it continues to work with legacy code.

Step 4: Change the last line to:

$v_0.updateRefinementFilters(name, $v_3, searchBoolean, useKQL, $v_4);

We've overridden the original hardwired 'OR', to our searchBoolean param!

PART 2 - Display Template

Step 1: Edit the Filter_MultiValue_body.html display template (technically you should create a copy and then set the refinement to use your custom multi-value refinement)

Step 2: Locate this section around line 90:

 <div id="SubmitValue">
                        <div id="submit">
                            <a onclick="Srch.Refinement.submitMultiRefinement('_#= $scriptEncode

Step 3: Change the onclick to:

onclick="Srch.Refinement.submitMultiRefinement('_#= $scriptEncode(propertyName) =#_', $getClientControl(this), _#= $htmlEncode(useContains) =#_, _#= $htmlEncode(useKQL) =#_,'AND');

Add a fifth string param to the function in the last line. Note I have added the 'AND'. The AND (or OR) will be passed as the searchBoolean param in the function within the mods made earlier.  If we don't pass anything the default is applied in the function.

Reset IIS to be sure and it should now work!!

The correct way to implement this is to copy the function and paste it into the refinement template. In working with Mikael Svenson (Microsoft MVP) on the same problem, he added these example steps (which I modified to flow with CCDW's answer):

What you would do in your refinement template is something like this:

TheMan.Search.submitMultiRefinement = function(name,control,useContains, useKQL, searchBoolean) {
 // copy the contents from search.clientcontrols.debug.js
 // change the last line to use searchBoolean instead of "OR"  (as explained in Part I - Step #4 above)

Then change your onclicks to read TheMan.Search.submitMultiRefinement() instead of Srch.Refinement.submitMultiRefinement()



1 comment:

  1. Hi,
    It's always fun to get a challenge :)

    I think it's imporant to point out that you should never modify the .js files coming with SharePoint as you never know when they will be overwritten with a CU/PU, but extending on them seems a must in 2013. And with the added benefit of working in SharePoint Online as well :)

    Mikael Svenson