Saturday, February 24, 2018

Sitecore-Azure : Highlight search term in Azure Search Results

In my previous, we searched for a Sitecore item based on item id in Azure search index. Let us take a different example this time to see how to achieve search term highlighting in your project if you are using Azure search.

Suppose we have a FAQ page where a user can search for frequently asked questions.  We created a template for FAQ item with fields Question and Answer. Now suppose I want to search “Working hours” in the FAQ list I will fire below query in Azure Search Explorer:-
search=working hours&$select=question,answer&$filter=template_1 eq 'a68fcde9c8e34172aeac251f315ca7e5' and language_1 eq 'en'

In above query:-
1.       Search term is working hours
2.       Field to retrieve are question and answer
3.       We are filtering the results based on the template id of FAQ Item and English language
4.       Let us update search parameter class which we created in previous post
public class SearchParams
    {
        public SearchParams()
        {
            SortBy = new List<SortQuery>();
            FieldsToSearch = new List<string>();
            FieldsToRetrieve = new List<string>();
            SearchFilterQuery = new List<Tuple<string, string, string, string>>();
            Skip = 0;
            Top = 100000;
            FieldsToHighlight = new List<string>();
            HighlightPreTag = "<b>";
            HighlightPostTag = "</b>";
        }

        public List<Tuple<string,string,string,string>> SearchFilterQuery { get; set; }
        public int Top { get; set; }
        public int Skip { get; set; }       
        public IList<SortQuery> SortBy { get; set; }
        public IList<string> FieldsToSearch { get; set; }
        public IList<string> FieldsToRetrieve { get; set; }
        public bool IncludeTotalResultCount { get; set; }
        public IList<string> FieldsToHighlight { get; set; }
        public string HighlightPreTag { get; set; }
        public string HighlightPostTag { get; set; }
    }
5.       Now add fields in which you want to highlight the search text.
public List<FaqItem> GetFaqBySearchTerm(string searchTerm, string language)
    {
        LoggerHelper.WriteDebug("GetFaqBySearchTerm method: Started");
        var faqItems = new Lsit<FaqItem>();
        try
        {
            var fieldsToretrieve = new List<string>();
            fieldsToretrieve.Add(Constants.Question);
            fieldsToretrieve.Add(Constants.Answer);

            var results = GetFaqFromAzure(searchTerm, Constants.FaqTemplateId, fieldsToretrieve, language);
            if (results != null && results.Results.Count > 0)
            {
                foreach (var item in results.Results)               
                {
                                   FaqItem faq = new FaqItem();
                    faq.Question = item.Document.Question;
                        if (item.Highlights != null && item.Highlights.ContainsKey(Constants.Question))
                        {
                            var highlights = item.Highlights[Constants.SearchFaqTitleField];
                            faq.Title =GetHighlighedString(faq.Title, highlights);
                        }
                        faq.Answer = item.Document.Answer;
                        if (item.Highlights != null && item.Highlights.ContainsKey(Constants.Answer))
                        {
                            var highlights = item.Highlights[Constants.Answer];
                            faq.Description =GetHighlighedString(faq.Answer, highlights);                           
                        }
                    faqItems.Add(faq);
                }
            }
        }
        catch (Exception exc)
        {
            LoggerHelper.WriteDebug(string.Format("GetFaqBySearchTerm method Exception occured", exc.Message));
            throw;
        }
        LoggerHelper.WriteDebug("GetFaqBySearchTerm method: End");
        return faqItems;
    }


    
private DocumentSearchResult<FaqSearchResult> GetFaqFromAzure(string searchTerm, string templateId,
        List<string> fieldsToretrieve, string language = "en", List<SortQuery> sortQueries = null)
    {
        DocumentSearchResult<LinkBoxSearchResult> response = null;
        if (!string.IsNullOrEmpty(searchTerm) && !string.IsNullOrEmpty(templateId))
        {
            string searchText = Constants. searchTerm;

            SearchParams searchParameters = new SearchParams();

            //Filter For language
            searchParameters.SearchFilterQuery.Add(new Tuple<stringstringstringstring>(Constants.LanguageField,
            Convert.ToString(Enums.SearchOperator.eq), "'" + language + "'", Enums.MultiCriteriaOperation.and.ToString()));

            //Filter For template
            searchParameters.SearchFilterQuery.Add(new Tuple<stringstringstringstring>(Constants.TemplateField,
            Convert.ToString(Enums.SearchOperator.eq), "'" + GenericUtilities.GetAzureFormattedGuid(templateId) + "'"string.Empty));

            ////Field That We want to Show records in View Page
            searchParameters.FieldsToRetrieve = fieldsToretrieve;

            searchParameters.FieldsToHighlight.Add(Constants.Question);
            searchParameters.FieldsToHighlight.Add(Constants.Answer);

            //How many records want to display page at a time
            searchParameters.Top = 1;
            //If Skip Count has any count value
            searchParameters.Skip = 0;

            if (sortQueries != null)
                searchParameters.SortBy = sortQueries;

            response = GetFaq(searchTerm, searchParameters);
        }
        return response;
    }

    private DocumentSearchResult<FaqSearchResult> GetFaq(string query, SearchParams searchParams)
    {
        ISearchIndexClient searchIndexClient = SearchServiceOperations.CreateSearchIndexClient();
        SearchParameters parameters = new SearchParameters()
        {
            Filter = QueryBuilder.GenerateFilterQuery(searchParams.SearchFilterQuery),
            OrderBy = QueryBuilder.GetSelectedSort(searchParams),
            QueryType = QueryType.Full,
            SearchFields = searchParams.FieldsToSearch,
            IncludeTotalResultCount = searchParams.IncludeTotalResultCount,
            Select = searchParams.FieldsToRetrieve,
            Skip = searchParams.Skip,
            Top = searchParams.Top,
            HighlightFields=searchParams.FieldsToHighlight,
            HighlightPreTag=searchParams.HighlightPreTag,
            HighlightPostTag=searchParams.HighlightPostTag
        };
        return searchIndexClient.Documents.Search<LinkBoxSearchResult>(query, parameters);
    }

        private string GetHighlighedString(string value, IList<string> highlights)
        {
            if (!string.IsNullOrEmpty(value) && highlights.Any())
            {
                var hits = highlights.Select(h => h.Replace("<b>", string.Empty)
                                .Replace("</b>", string.Empty)).ToList();
                for (int i = 0; i < highlights.Count; i++)
                {
                    value = value.Replace(hits[i], highlights[i]);
                }
            }
            return value;
        }
}



No comments:

Post a Comment