Have a #Bing / #Google like search experience in #SPO using Azure Cognitive Services

Hi,

Microsoft recently made Azure Cognitive Services available (in preview at the time of writing). This new set of APIs is built on top of Azure’s API Management building block and points to well known APIs (Machine Learning, Bing…) that Microsoft was offering for a while but in different flavors. Thanks to Azure Cognitive Services, we now have a single way of consuming these APIs which makes our life better!

The Bing AutoSuggest API can be very handy to improve any search experience. In SharePoint Online, one can use Query Suggestions but they are defined at tenant level and they need to be imported upfront. This is not that user friendly. So, what if you could simply have a Bing/Google like experience that is suggesting queries as you type? That’s what we’ll do very easily in this post.

If like me, you only believe what you see, you can have a look at a live demo here:

Note : for this example, I have not been using the SharePoint Framework (SPFx) but simply jQuery UI’s autocomplete control in combination with Azure Cognitive Services. So, here are the steps to build such a control:

  • Go to https://portal.azure.com/ and look for the Cognitive Services:
    cog3.png
  • Create a new Cognitive Services Account in order to end up with something like this:
    cog4
    the important part is highlighted in red. I’ve chosen the Standard pricing tier (no free one) and I’ve specified the Bing Autosuggest API.
  • Once done, grab one of the keys that was generated for you as you’ll need it later on:
    cog5
    The Azure part is done.
  • Now, in a SharePoint search center, add a Snippet Editor to the default page
  • In the Snippet Editor, add the code that I will show you later in this post
  • Go to the webpart properties ==> advanced section, and enable the webpart to be exported as illustrated below:cog1
  • Now that the webpart can be exported, you can do so, this will generate a .webpart file:cog2.png
  • This webpart file may now be imported in any site collection via the webpart gallery.

So, here is the code that you have to put in the Snippet Editor, again, feel free to use your preferred JavaScript framework, my point is to use Azure Cognitive Services, not to give JavaScript lessons :).

	<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
	<link rel="stylesheet" href="/_layouts/15/1033/styles/Themable/searchv15.css?rev=gHovyF1PT%2BErZeM0JGVoew%3D%3DTAG325">
<script src="//code.jquery.com/jquery-1.12.4.js"></script>
<script src="//code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div class="ms-srch-sbLarge ms-srch-sb-border">
    <input placeholder="Type something..." id="keywords">
    <a title="Search" id="SearchLink" class="ms-srch-sb-searchLink" href="javascript: {}">
        <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACiUlEQVRYR+2Wv4sTURDHZ94GQxqJByb5A+QqOQ/RTkE8RLTQRiKHp4gWabLvJV7wGtHIiYWFm/cSkkotPD200srzwMYflT9QrlFbq8Rf0S7J7o48MCAr2bdB4ikk3TI/3mdmvswEYZ1/uM7vwxjg/+lAvV7f1Ov1TiPiYQDYCgAbAeA7Ea0h4n3P864Vi8X2sJqK1AGl1EkAuAIAK4h4CxFfpFKpdqvVSnqetxMAjiHifiKaF0LcHAbCCFCpVBYB4IhlWVnbttcGJVdKbSOiuwCwLIQoR4UIBdCV+76/4Lru7lKp9MmUVCm1mYieMsYWbdteMvlr+0AAPXPXdd8h4kxY5cFHHMeZtixr1fO8ySiaGAggpSwh4hTn/ESUSn71UUotEdErIcRVU+xAAKXUE0S8ZNv2Q1OSoL1arR4gogXO+R5TbBjAV8bYlnw+/9mUJGhvNBqpTqfztlAoTJhiwwC8TCazIZvNeqYkQXu5XI4lk8luoVBgpth/twNSyscAcFkIsWKqImiXUh5ExLN/qoF5IpoWQhwfFqBSqdy2LOu5bduOKXbgCBzHSVqW9R4A9nHO35gS9e21Wm2767oPEonEZC6X+2aKC92EUkpd/TlE3MU5/2hKptXf6/WeAcB5zvmyyT90E/aDpZR6r8/6vn+0WCy+HpRUV+77/h0A+MA53xvl8UgA2qlarc4Rkd5qq/oaxmKxl81m80s6nZ7odrs7iGgOAGYA4BFjbJaILkY9SMZr2K9Ea4IxdgoRD/m+PwUA+lvPWOvjXjwev6FnrjuGiBeiQkQGiNpS7TcMxEgAhoEYGUBUiJECBCD037XfzvPIAX5CnEHENuf8elBLfwUgTMBjgHEHfgB2xxwweE1PpAAAAABJRU5ErkJggg==">
    </a></div>
<script type="text/javascript">
$(function () {
    function DoSearch() {
        var url = window.location.toString();
        var k = $('#keywords').val();
        if (k == '')
            k = '*';
        if (url.indexOf('/default.aspx') != -1) {
            url = url.replace("/default.aspx", "/results.aspx");

        }
        url = url + '#k=' + encodeURIComponent(k);
        window.location = url;
    }
    $("#SearchLink").click(DoSearch);
    var KeywordIndex = window.location.toString().lastIndexOf('#k=');
    if(KeywordIndex!=-1)
    {
        var LastK = decodeURIComponent(
            window.location.toString().substring(KeywordIndex).replace('#k=', ''));
        var LanguagePosition=LastK.indexOf('#l=');
        if(LanguagePosition != -1)
        {
        $("#keywords").val(LastK.substring(0,LanguagePosition));
        }
        else
        {
        $("#keywords").val(LastK);
        }
    }
    $("#keywords").keydown(function(event){
        if(event.keyCode == 13) {
            if($("#keywords").val().length!=0) {
                DoSearch();
            }
            event.preventDefault();
            return false;
        }
    });
    $('#keywords').css('width', '450px');
    $( "#keywords" ).autocomplete({
        delay: 0,
        minLength:3,
        source:function(request,response){
	        var k = request.term.replace('+',' ').replace('-',' ').replace('"','');
            $.ajax({
                url: "https://api.cognitive.microsoft.com/bing/v5.0/suggestions?q=" + k + "&mkt=en-us",
                headers: { 'Ocp-Apim-Subscription-Key': '<yourkey>' }
            }).done(function (data) {
            if (data != null && data.suggestionGroups.length > 0)
            {
		        var availablekeywords = [];
                for (var i = 0; i < data.suggestionGroups[0].searchSuggestions.length; i++)
                {
                    availablekeywords.push(data.suggestionGroups[0].searchSuggestions[i].displayText);
                }
		        response(availablekeywords);
            }});
        }});
});
</script>

The important part here is the communication with the Bing AutoSuggest API which is handled by the AJAX call. You’ll simply have to update the key value that is associated with the Ocp-Apim-Subscription-Key HTTP header. As you should have noticed yourself by now, Azure Cognitive Services are CORS compliant, which is great for scenarios like this one. However, one should keep in mind that the subscription key is revealed as anyone launching the browser dev tools can see it. Of course, there is no sensitive information here since it’s just a matter of getting query suggestions back but anyone in the world holding your key could start consuming the API with you paying for it!

As a mittigation measure, keys can be regenerated at any time from the Azure Portal. If you don’t want to take any risk, you should build your own intermediate API in Azure PaaS, protected by Azure AD and let this one use the subscription key. This is of course more complicated and will cause a performance overhead because of the extra hop. I’d say that in this particular case, since there is no sensitive information at all, it’s worthwhile to take the risk.

Happy Coding!

About Stephane Eyskens

Office 365, Azure PaaS and SharePoint platform expert
This entry was posted in Azure, Azure Cognitive Services, SharePoint Online and tagged , . Bookmark the permalink.

5 Responses to Have a #Bing / #Google like search experience in #SPO using Azure Cognitive Services

  1. Reza says:

    That was really inspiring man! Thanks for sharing.

    Like

  2. Philip says:

    I tried this approach, but it does not return any results from my site. Any idea on this?

    Like

Leave a comment