25 July 2015

Site search and Predictive

I had an interesting requirement about a predictive search. The requirement was to propose terms when a user start entering text on the Search Box:


After a few thoughts we have considered the following approach let's make those terms propositions coming from the website content. As a matter of fact why not using the index to search for the term and return the short list required. What would we need:

  1. WebAPI call from the View
  2. A search Service on the .NET side that will query the index and bring the result
So It sounds quite simple.

So let's setup the Controller for your WebAPI. this could be something like:

namespace XXX.Web.Controllers.XXX.API
{
    [RoutePrefix("webapi/v1/search")]
    public class SuggestiveSearchController : ServicesApiController
    {
        private readonly ISuggestiveSearch _searchService;

        public SuggestiveSearchController(ISuggestiveSearch suggestiveSearchServices)
        {
            _searchService = suggestiveSearchServices;
        }

        [HttpGet]
        [Route("autocomplete")]
        public AutoCompleteSuggestionList Autocomplete(string query)
        {
            if (string.IsNullOrEmpty(query))
                return null;

            return _searchService.AutoCompleteTerm(query);
        }
    }
}


Now, on your View you will have something that calls your WebApi:

            $(document).ready(function () {
                $("#keyword.autocomplete").autocomplete({
                    serviceUrl: '/webapi/v1/search/autocomplete'
                });
            });


Make sure your route will resolve and Sitecore will not resolve your WebAPI route. For that you could use the Attribute routing as per the really nice article from Bart Bovendeerdt on the following link: http://wp-bartbovendeerdtcom.azurewebsites.net/sitecore-8-webapi-v2-mvc-and-attribute-routing/

Then on your service level, you will then retrieve your list of suggestion through Sitecore Content Search - here would be a quick draft...

        public AutoCompleteSuggestionList AutoCompleteTerm(string term)
        {
            var result = new AutoCompleteSuggestionList();
            var list = new List();

            if (String.IsNullOrEmpty(term))
                return result;

            result.query = term;

            var sitecoreService = new SitecoreService(_databaseContext.GetDatabaseName());
            var home = sitecoreService.GetItem(_siteContext.GetStartPath());
            var index = _contentSearchContext.GetIndex(new SitecoreIndexableItem(home));

            using (var context = index.CreateSearchContext(SearchSecurityOptions.DisableSecurityCheck))
            {
                var suggestionsKeywords = context.GetTermsByFieldName("keywords", term);
                foreach (var suggestion in suggestionsKeywords 
                {
                    list.Add(suggestion.Term);
                }
            }
            if (list.Count <= 0)
            {
                result.suggestions = list;
                return result;
 
            }

            result.suggestions = list.Distinct().Take(10).ToList();
            return result;
        }
    }

No comments:

Post a Comment