Sitecore SXA – Sort by title does not work

Please note that my suggested solution isn’t specific for SXA. You can use this without SXA, as it introduces a new computed field.

The SXA Sort Results component lets you sort your search results based on the Sortings that you define within /sitecore/content/Your Tenant/Your Site/Data/Search/Sort Results.
This functionality will make use of the default Solr sorting, to sort the results based on the field that is specified.

Out of the box, SXA ships with the Title Asc and Title Desc sorting options. I’m not sure who would ever want to sort their search results based on title, but as the option is there, it should also work. This however isn’t the case. The sorting based on title, or any text field, will not work, as the field is tokenized within Solr.

For the text fields this means that the value is split on whitespaces, which means that This is an example will be saved as seperate words; This, is, an, example within the Solr index. When you want to sort on this field, it won’t sort on the real value, but on the tokenized value, meaning that the sorting will not give the expected results.

When you want to sort on a specific field, always make sure the field isn’t tokenized within Solr, and that the casing of the values is always the same, Test would be sorted differently then test.

This means that when you want to sort on Title, that you should add an extra field that isn’t tokenized, and that is lowercase. The solution below is a Sitecore based solution, so that the Solr schema does not have to be edited manually.

First of all we create a Computed Field class, which uses the ReferenceField as a reference to the field from where it should take the value from.

namespace Example
{
    public class SortReferenceComputedField : IComputedIndexField
    {
        public string FieldName { get; set; }
        public string ReturnType { get; set; }

        public string ReferenceField { get; set; }

        public object ComputeFieldValue(IIndexable indexable)
        {
            var indexItem = indexable as SitecoreIndexableItem;

            var field = indexItem?.Item?.Fields[ReferenceField];
            if (field != null && field.HasValue)
            {
                return field.Value.ToLower();
            }

            return null;
        }
    }
}

After that, all we have to do is register the Computed Field by adding a configuration file. Please note that you can use the same SortReferenceComputedField type for each field that you want to be able to sort on.

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:search="http://www.sitecore.net/xmlconfig/search/" xmlns:role="http://www.sitecore.net/xmlconfig/role/">
  <sitecore role:require="Standalone or ContentManagement or ContentDelivery" search:require="solr">
    <contentSearch>
      <indexConfigurations>
        <defaultSolrIndexConfiguration type="Sitecore.ContentSearch.SolrProvider.SolrIndexConfiguration, Sitecore.ContentSearch.SolrProvider">
          <documentOptions type="Sitecore.ContentSearch.SolrProvider.SolrDocumentBuilderOptions, Sitecore.ContentSearch.SolrProvider">
            <fields hint="raw:AddComputedIndexField">
              <field fieldName="sorttitle" referenceField="title" storageType="no" indexType="untokenized">Example.SortReferenceComputedField, Example</field>
            </fields>
          </documentOptions>
        </defaultSolrIndexConfiguration>
      </indexConfigurations>
    </contentSearch>
  </sitecore>
</configuration>

As you can see in the example above, we create a new field called sorttitle that uses the value from the title field. For the last step, just go to the Title Asc and Title Desc sortings, and make sure that the facet that is used there, points to the newly created sorttitle field.

The SOLR way

Of course this can be done in Solr as well, however i’ve chosen the implementation above, so that you do not have to (manually) edit the managed-schema within Solr. If you would like to do this in Solr, create a new field type with the LowerCaseFilterFactory and the TrimFilterFactory as indexing analyzers, and then use a copyField definition create the field.

Leave a Reply

Your email address will not be published.