Faceted Autocomplete for a Sitecore Multilingual site using SOLR Suggester API

There are lot of options for SOLR Autocomplete and the popular ones are NGrams, Terms Component and Suggester. Suggester is the most recent, fastest and most recommended one.

Though faceting/filtering of results based on template or any other field may seem to be difficult with Suggester, it is possible with a minor tweak!!

Create Field for Building Suggestions

The field from which suggestions have to be built can be a Sitecore field or a custom computed field. In my case it involved few Sitecore fields like Title, Subtitle, Description etc.. So I created a copy field with these as below.

<field name="_suggest" type="text_general" indexed="true" stored="true"/>
<copyfield source="title_t" dest="_suggest"/>
<copyfield source="subtitle_t" dest="_suggest"/>
<copyfield source="description_t" dest="_suggest"/>

Creating Field Type for Suggester

This fieldtype will be used by suggester for analyzing and building the suggestions from our field (_suggest). We can either use existing field types like text_general etc. or create a fieldtype like the one below (in the schema.xml file) in case any customization may later be required.

<fieldtype name="text_suggester" class="solr.TextField" positionincrementgap="100">
    <analyzer>
        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
        <filter class="solr.LowerCaseFilterFactory"/>
        <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
        <charfilter class="solr.PatternReplaceCharFilterFactory" pattern="[^a-zA-Z0-9]" replacement=" "/>
    </analyzer>
</fieldtype>

Creating The Suggest Component:

Though we have many Lookup Implementations for creating Suggest Component, but Context Filtering and Payload Fields are supported only by AnalyzingInfixLookupFactory and BlendedInfixLookupFactory.

Out of these, AnalyzingInfixLookupFactory doesn’t remove duplicate suggestion values. So I preferred BlendedInfixLookupFactory, which returns only unique values though the search term is present in multiple indexed documents.

Since we need to get the suggestions only for the current language (by Context Filtering) we should have contextField set as _language (this SOLR field of indexed document corresponds to Sitecore Item’s Language).

SOLR has come up with a Payload field for purposes like boosting, tagging etc. but it can be used for other purposes too. Here we can use it for faceting results!! In my case I wished to group results based on a sitecore field, Facet Category.

<searchcomponent name="suggest" class="solr.SuggestComponent">
    <lst name="suggester">
        <str name="name">suggester</str>
        <str name="lookupImpl">BlendedInfixLookupFactory</str>
        <str name="dictionaryImpl">DocumentDictionaryFactory</str>
        <str name="field">_suggest</str>
        <str name="contextField">_language</str>
        <str name="payloadField">facet_category_t</str>
        <str name="suggestAnalyzerFieldType">text_suggester</str>
        <str name="buildOnStartup">false</str>
        <str name="buildOnCommit">false</str>
    </lst>
</searchcomponent>

Creating Request Handler:

We need to create a request handler pointing to our suggest component, that will help in building and retrieving suggestions.

<requesthandler name="/suggest" class="solr.SearchHandler">
    <lst name="defaults">
        <str name="suggest">true</str>
        <str name="suggest.dictionary">suggester</str>
        <str name="suggest.onlyMorePopular">true</str>
        <str name="suggest.count">10</str>
        <str name="suggest.collate">true</str>
    </lst>
    <arr name="components">
        <str>suggest</str>
    </arr>
</requesthandler>

Once we are done with this, we can query and check for results in xml format,
http://localhost:8983/solr/sitecore_web_index/suggest?suggest.q=apple&suggest.cfq=fr-CA

Building jQuery Autocomplete:

We can use getJSON API to retrieve the suggestions in json format and display after adding querystring ‘wt=json’.
An Example below,

<input id="search-box" type="text" />
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20type%3D%22text%2Fjavascript%22%3E%0A%24('%23search-box').autocomplete(%7B%0A%20%20%20%20source%3A%20function%20(request%2C%20response)%20%7B%0A%20%20%20%20%20%20%20%20var%20currentLanguage%20%3D%20'en'%3B%0A%20%20%20%20%20%20%20%20var%20url%20%3D%20%22http%3A%2F%2Flocalhost%3A8983%2Fsolr%2Fsitecore_master_index%2Fsuggest%3Fsuggest.q%3D%22%20%2B%20request.term%20%2B%20%22%26suggest.cfq%3D%22%20%2B%20currentLanguage%20%2B%20%22%26wt%3Djson%22%3B%0A%20%20%20%20%20%20%20%20%24.getJSON(url%2C%20function(data)%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20response(%24.map(data.suggest.suggester%5Brequest.term%5D.suggestions%2C%20function(value)%20%7B%20return%20value.term%20%7D))%3B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%7D%0A%7D)%3B%0A%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />

In case if you face any Cross Domain issues, you need to add the filter component as mentioned in the below url to your web.xml http://marianoguerra.org/posts/enable-cors-in-apache-solr.html Don’t forget to change param-value if your SOLR is hosted in a different server.

 

Happy Searching!!

References:
https://cwiki.apache.org/confluence/display/solr/Suggester
https://blog.horizontalintegration.com/2015/07/20/configuring-solr-to-provide-search-suggestions/

Originally Posted at:  https://www.nttdatasitecore.com/Blog/2017/January/Faceted-Autocomplete-for-a-Sitecore-Multilingual-Site-using-SOLR-Suggester-API

Leave a Reply

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