Using Azure Search from PHP

Updated March 2, 2016: Source code for this post is available on GitHub .

Updated March 3, 2015: Azure Search is now generally available – updated pricing tier info and API version info.

Updated February 14, 2016: Fix dead links.

I recently had to present at a local PHP meetup where I gave an introduction to Microsoft Azure. As part of this I worked out some sample code on how to integrate the Azure Search service in a PHP website. With Azure Search you can easily integrate sophisticated search capabilities into your websites or applications without having to deal with all the hassle for maintaining a search index.

In this post we’ll create a simple PHP website that lists hotels and allows for searching them based on different criteria. The website supports free text search, auto-completion, and faceted search.

Azure Search in PHP

TL;DR

Azure Search provides a REST-based API to perform index management (creating, populating, …) as well as to perform queries on the search indexes.  In the PHP website you can leverage this REST API to add search capabilities to the site.

Perform the following steps to do so:

  1. Create a free Azure Search service instance in the Azure Preview portal. The process is described in the following post.
  2. Invoke the Azure Search REST API, for example using the Httpful PHP library or curl, passing in the api-key of the instance created in the previous step, and passing in a search term you got from user input.
  3. Display the search results from the resulting JSON output.
  4. Additionally, you can further leverage the REST API to also provide auto-completion and facetted search.

 

Getting Started

Creating the Search service and index

As a first step in working with the Azure Search service, you need to create a new Azure Search instance. As an Azure subscriber you have access to a free shared, multi-tenant Search service. The Azure Search functionality is made available through the Azure portal, or using a REST API.

Search pricing tiers

Once you have a Search service up and running, you can start creating an index. This search index defines the fields a document is made of, the fields that you can search on or that can be used for suggestions, as well as attributes that control the query behavior (e.g. scoring profiles, sorting, etc).  To interact with the search service you can use the

You can run DotNetHowTo in the ‘Getting Started’ GitHub repo to setup your Search instance, create an index and populate the index with documents.

Adding basic search to our website

To create the search index and populating it with data you have used the Azure Search REST API using Fiddler, Postman or any other REST client of your preference. For integrating the search functionality in the PHP website, we’ll be also be using the REST API.

To implement the basic search functionality, allowing a user to search the list of hotels, we need to issue a Search request, which is a GET request on our index:

GET /indexes/ [index name] /docs?[query parameters]

Using the search query parameter, we can specify the text to be searched for. When you create the search index, you indicate which fields are searchable. By default, all searchable fields in the index will be searched.

Note that with every REST call you are required to always specify the api-version parameter. If you don’t specify this parameter, you’ll get an HTTP 400 error with the cryptic “An error has occurred” message.

Below code sample shows how it’s done from PHP – in this sample I’ve also added sorting based on the baseRate field using the $orderby parameter.

$term = "<search term>";
$searchUri

  = "

https://<your service>.search.windows.net/indexes/
hotels/docs?search=$term&\$orderby=baseRate
&api-version=2015-02-28

 ";

// Invoke the Search REST API $response

  = \Httpful\Request::get(

$searchUri

 )
    ->addHeaders(

array

 ('

api-key

 ' => '

<your search key>

 '))
    ->expectsJson()
    ->sendIt();

Once you have invoked the Search service, the results will be provided as a JSON document. We can now retrieve the search results from the body, in the value field:

foreach

 (

$response

 ->body->value 

as$result

 )
{
   

$formattedPrice

  = 

sprintf

 ("%.2f", 

$result

 ->baseRate);
   

echo

  "

$result

 ->hotelName 

$result

 ->rating 

$$formattedPrice

 ";
}    

For our sample website, this now allows the user to specify a search term, which will be used to search the list of hotels, match the term in the hotelName, description, category and tags searchable fields.

Basic search

 

Providing search suggestions using auto-completion

In addition to searching the index, we can assist the user by providing search suggestions. This is achieved using the Suggestions REST API . This API will leverage the fields in the index that were marked as suggestions (e.g. hotelName and description).

The basic structure for the Suggestions API is the following:

GET /indexes/[index name]/docs/suggest?[query parameters]

At a minimum you need to provide the search parameter, which is the text to use to suggest queries, and which must be at least 3 characters. As mentioned, don’t forget to also specify the api-version parameter.

In below code sample, we’re providing the user with the hotel name and description as search suggestion. Put below code snippet in a separate file (e.g. gethotelautocomplete.php); this file can then be bound to the autocomplete event of the search input field on the web page.

$searchUri

  = "

https://<your service>.search.windows.net/indexes/
hotels/docs/suggest?search=$term
&api-version=2015-02-28

 ";

// Invoke the Search REST API $response

  = \Httpful\Request::get(

$searchUri

 )
    ->addHeaders(

array

 ('

api-key

 ' => '

<your search key>

 '))
    ->expectsJson()
    ->sendIt();

$json

 =

array

 ();

$suggestions

  = 

$response

 ->body->value;
    

foreach

 (

$suggestionsas$suggestion

 )
{
    $json[]=

array

 (
        'value'=> 

$suggestion

 ->hotelName,
        'label'=> "

$suggestion

 ->hotelName (

$suggestion

 ->description)"
        );
}

echo

  json_encode(

$json

 );

To bind the above autocompletion logic to the search field, add following Javascript code to the search web page:

<!-- Autocomplete script, the search field has 'term' as ID -->

 <

scripttype

 ="

text/javascript

 ">
        $(document).ready(

function

 (){
            $("

#term

 ").autocomplete({
                source:'

/gethotelautocomplete.php

 ',
                minLength:

3

             });
        });
</script>

With the above code you should now have autocompletion functionality added to the site. As soon as you type 3 letters or more, the search service Suggestions API is invoked and results are provided to the user:

Search suggestions

 

Adding faceted search to the website

Now that we basic search functionality added to our website, we can take it one step further, namely by adding faceted search. With faceted search you can search for documents in your index using categories. For example, for each hotel in our index we have the base rate for a room per night.  Using faceted search we can specify price ranges for this base rate and then search for all hotels that match a specific price range. When creating the search index you can specify which fields can be used as facets.

To implement faceted search we leverage the basic Search REST API. First you need to specify which facets you want to retrieve using the facet query parameter. In the search results you will then get the document count for each facet value.

In below example we indicate that we want to use facets for rating, category and baseRate. For the baseRate field we specify the price ranges: 0-100, 100-200, 200-500, 500-1000 and >1000.

GET /indexes/hotels/docs?search=&facet=rating&facet=category&facet=baseRate,values:100|200|500|1000&api-version=2015-02-28

To filter based on a given facet value, for example retrieve the hotels in a given price range, we use the $filter query parameter. In below example, we retrieve the hotels within the price range 100-200.

GET /indexes/hotels/docs?search=&facet=rating&facet=category&facet=baseRate,values:100|200|500|1000& $filter=baseRate gt 100 and baseRate le 200&api-version=2015-02-28

Below code sample shows how this is done in our PHP website:

$term = "<search term>";
$searchUri

  = "

https://<your service>.search.windows.net/indexes/
hotels/docs?search=$term&\$orderby=baseRate
&facet=rating
&facet=category
&facet=baseRate,values:100|200|500|1000

&api-version=2015-02-28

 ";

// Invoke the Search REST API $response

  = \Httpful\Request::get(

$searchUri

 )
    ->addHeaders(

array

 ('

api-key

 ' => '

<your search key>

 '))
    ->expectsJson()
    ->sendIt();

The facet information (which facet values and document count per value) is available in the resulting JSON in the @search.facets property of body.

$propname

  ="

@search.facets

 ";                        

$facets

 = 

$response

 ->body->

$propname

 ;

$ratings

 =

$facets

 ->rating;

foreach

 (

$ratingsas$rating

 )
{
   

$ratingValue

  = 

$rating

 ->value;
   

$ratingCount

  = 

$rating

 ->count;
}

You can then display these facet values and counts in the website. As you drill further into facets, the document counts will be updated to reflect the selected filters. For example, as you select the hotels with a rating of 4, you’ll notice that the number of categories is also adjusted.

Faceted Search

 

Conclusion

In this article we’ve gone through adding search as a service using Azure Search to your PHP website.  In a matter of minutes you can get started and provide your users with a complex search functionality. And as your site gets more traffic, you can easily scale out your search service.

Make sure to get started with the Azure Search service and also try out the other application, data and infrastructure services in the Microsoft Azure platform. You can get started for free on Azure or activate your MSDN Azure benefits.

Additional resources can be found here: