Tuesday, August 26, 2014

SharePoint 2010 Enterprise Search Grouping

In the previous post, we discussed sorting the search results of the core search results web part by our custom search properties. This can be achieved by extending the core search results web part and overwriting the ConfigureDataSourceProperties() method.
It is also possible to group the results by a property or even a combination of properties.

For example, if I have 2 managed properties called 'MyDepartment' and 'MyReportType' and I would like to see the results grouped by all possible combinations of these two properties, such as:

Asset Management - Account Activity  -

  • Account Activity for Account A and Quarter 1
  • Account Activity for Account B Q4

Asset Management - Asset Acquisitions -

  • Asset Acquisitions 2014
  • Asset Acquisitions Feb 2014

Asset Management - Quarterly Income Reports +
Compliance - Quarterly Compliance Report  +
Investment Management - Risk Analysis +
Investment Management - Risk Decomposition +

, each one with a suite of reports within each group, where inside each grouping the reports would be sorted by other managed properties, such as a specific date property for example.
The group by criteria is bolded out and on expand (+) it would show all results for the group.

As a first step, the group-by properties need to be added to the sort-by collection, in their order of relevance. Note the MyDepartment is the first sort criteria, alphabetically ascending, followed by 'MyReportType':

                   // get the datasource and change the sort order
                    CoreResultsDatasource dataSource = this.DataSource as CoreResultsDatasource;
                    if (sortBy != string.Empty)
                        dataSource.SortOrder.Add("mydepartment", sd);
                        dataSource.SortOrder.Add("myreporttype", sd);


In the XSLT we will generate the presentation of the group, by applying the Muenchian method, found on Jeni Tennison's site:

  1. First we declare a key in the declaration area of the XSLT:
    <xsl:key name="gg" match="/All_Results/Result" use="concat(mydepartment, myreporttype)"/>
  2. We modify the regular body template to perform two for-eaches, one for the group-by criteria and another one for the results within each group-by value:

<xsl:template name="dvt_1.body">
    <xsl:for-each select="/All_Results/Result[count(. | key('gg', concat(mydepartment,myreporttype))[1]) = 1]">
        <td colspan="8">
           <xsl:value-of select="
          <xsl:text> - </xsl:text>
          <xsl:value-of select="
          <xsl:text> + </xsl:text> <!-- additional html and javascript to achieve expand-collapse-->
      <xsl:for-each select="key('gg', concat(
        <xsl:sort select="myeffectivedate" order="descending"/>
        <xsl:call-template name="dvt_1.rowview"/>

3. Inside the inner for-each, specify the sort criteria to be the date column. The results are rendered by calling the dvt_1.rowview template.