Azure Search Suggesters: Helping users to find search keywords

Search is important feature of many apps and web sites because it is the main way for users to find quickly the information they are looking for. Typing search keywords to search box is not the end point of search we can provide to users. Sites that have huge amount of data can also help users to find out what keywords to use. In this post I will show how to use Azure Search suggesters to help users to find out these keywords.

NB! Some parts of this post are using code from my previous Azure Search post Writing simple REST-client for Azure Search. If Azure Search is new for you I also suggest you to read my post about search planning Planning and creating Azure Search indexes.

Suggesters and search

To understand suggesters better let’s see the fragment of my sample web.

Azure Search Suggesters: Search box with suggestions

There is search term “ale” typed to search box. As you can see this search box works like auto-complete box that displays list of items that user can select from if he or she wants to. These items are suggestions returned by suggester added to search index.

It’s not search but selection of possible keywords to try. These keywords are not arbitrary ones or like shots to darkness but the ones that really return results.

Creating suggester

Good news is that we can add suggesters through Azure portal. Bad news is we must add suggesters when we create search index. Currently it’s not possible to add suggesters later when index already exists. The following screenshot shows suggester tab of index form.

Suggester configuration

As you can see from screenshot above you can specify fields used by suggester. These fields are used for search when finding suggestions based on given search term.

Adding search field to page

For search field we will use simple HTML textbox. Using typeahead.js we will implement auto-complete functionality. Here is the search form with search field and submit button.

<form action="@Url.Content("~/Home/Search")" id="searchForm">
    <div class="input-group">
        <input type="text" placeholder="Search" class="form-control"
name="Term" id="searchTermField"
>
        <span class="input-group-btn"> 
            <button class="btn btn-primary" type="submit">Search</button>
        </span>
    </div>
</form>

To make suggestions work we use typeahead.js (make sure to include this script to your page). When at least three letters are typed to search box typeahead.js makes request to Suggest() action of Home controller.

<script type="text/javascript">
    jQuery(document).ready(function() {
 
        $('#searchTermField').val(searchTerm);
 
        $('#searchTermField').typeahead({ minLength: 3 }, {
            async: true,
            displayKey: 'value',
            source: function (query, processSync, processAsync) {
                var url = '@Url.Action("Suggest", "Home")';
                url += '?Term=' + query;
 
                return $.ajax({
                    url: url, 
                    type: "get",
                    dataType: "json",
                    success: function (data) {       
                        var matches = [];
                        $.each(data, function(i, str) {
                            if(str.Name)
                                matches.push({ value: str.Name });
                            else 
                                matches.push({ value: str });
                        });
                        return processSync(matches);
                    }
                });
            }
        });
    });
</script>

Now let’s add Suggest() method to Home controller.

public async Task<IActionResult> Suggest(string term)
{
    var result = await _searchService.Suggest(term);
 
    return Json(result);
}

We are using service layer to hide implementation details from presentation layer applications. We have search service as one of domain or application services and this is where search client is instantiated and used. Presentation layer must stay the same if we start using some other search technology.

Updating Azure Search REST-client

Now let’s update our Azure Search REST-client that we built in previous Azure Search post Writing simple REST-client for Azure Search.

public async Task<SuggestResponse> Suggest(string term)
{
    var url = string.Format("https://{0}.search.windows.net/indexes/products/docs/suggest", _serviceName);
    url += "?api-version=" + _apiVersion + "&search=" + WebUtility.UrlEncode(term);
    url += "&$select=Name&suggesterName=sg";
 
    var result = await Download<SuggestResponse>(url);
    return result;
}

We are using product names as suggestions shown to user. It’s too simplistic for real scenarios but it’s good enough for demo. Later in this post I will give you some advice how to get more advanced suggestions.

As with other Azure Search querying requests we get back response with list of values. We define class for return value that contains list of suggest items.

[DataContract]
public class SuggestResponse
{
    [DataMember(Name = "value")]
    public List<SuggestItem> Values;
}
 
[DataContract]
public class SuggestItem
{
    [DataMember]
    public string Key;
 
    [DataMember]
    public string Name;
}

To make my code easier to understand I show you my AzureSearchService Suggest() method that is called by presentation layer applications.

public async Task<string[]> Suggest(string term)
{
    var response = await _client.Suggest(term);
 
    return response.Values.Select(v => v.Name).ToArray();
}

This method makes call to REST-client suggest method. From suggestions it takes suggestions and returns this as array of strings. It’s minimal form of suggestions and this is exactly what we need in presentation layer.

Extending suggestions

What we did here this far is not everything we can do with suggestions. Our suggester is simple: it uses product names and long descriptions to find suggestion term and it returns product names as suggestions.

What we can do to get better or more advanced suggestions?

  • We can include more search fields to suggestions.
  • We can add manufacturer and category names to search index and return these too when getting suggestions. This way we can add these names too to suggestions shown to users.
  • It’s also possible to add additional fields to search index just for supporting suggestions.
  • When querying suggestions it’s also possible to set search filters and minimum index coverage percent.
  • We can also say if we want fuzzy results when also similarities are considered.
  • We can define more suggesters when creating search index.

It is possible to make different combinations out from ideas given above. As a search developer you just have to be creative and open-minded to get the best suggestions from the index you are working on.

Wrapping up

Suggesters are powerful feature of Azure Search that gives hints about search keywords and phrases to users. Suggesters are always part of some index and we must add suggesters to index when we create index. Currently it’s not possible to add suggesters later to index. Using suggesters is simple – we have to implement auto-complete for search box and then ask suggestions based on what user has typed to seach box. The code for this was simple and straightforward. We used REST-client created before and all we had to do was adding some new DTO-s and Suggest() method to our search service and REST-client. For sites with big amount of data we can be sure that well planned suggestions are create help for users.

Gunnar Peipman

Gunnar Peipman is ASP.NET, Azure and SharePoint fan, Estonian Microsoft user group leader, blogger, conference speaker, teacher, and tech maniac. Since 2008 he is Microsoft MVP specialized on ASP.NET.

    2 thoughts on “Azure Search Suggesters: Helping users to find search keywords

    • November 1, 2016 at 6:27 pm
      Permalink

      hi is there anyway i can download the code please

    • November 6, 2016 at 9:50 pm
      Permalink

      Hi! There’s no full code example available at the given moment. I will post update here if it happens one day. This far please take code from here and referred posts. It’s easy to make it work.

    Leave a Reply

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