Looking over the English dictionary for the word ‘facet’, I came to realize that facet means way more things that I originally knew: (according to http://dictionary.reference.com/browse/facet)

  1. one of the small, polished plane surfaces of a cut gem
  2. a similar surface cut on a fragment of rock by the action of water, windblown sand etc.
  3. aspect, phase, as in: ‘They carefully examined every facet of the argument’
  4. in Architecture, any of the faces of a column cut in a polygonal form
  5. in Zoology, one of the corneal lenses of a compound arthropod eye
  6. in Dentistry, a small highly burnished area, usually on the enamel surface of a tooth, produced by abrasion between opposing teeth in chewing

However, during this post I’m not going to discuss the origin of the word, but rather what a ‘facet’ means in terms of Azure Search.

Have you ever wondered how popular on-line shopping stored are able to create those complex filtering scenarios, different for every category of products and different in functionality as well? More specifically, how come high-end products show pricing categories based on a quite a few high price ranges while the accessories category comes with less, lower price ranges? Here’s an example on Amazon.co.uk:

You’ve probably also tried to create complex SQL queries over your Sales.Products table in order to come out with these complicated filtering scenarios and nobody blames you for that, but only God knows how much time you’ve spent trying to come up with a correct dynamic query for all your categories. I only wish the PM didn’t come up with another ‘brilliant’ idea of a filtering scenario during one of his hangover-morning :).

However, thanks to Azure Search, coming up with these filters based on your products or whatever you’re searching for within your application has now become child’s play! Seriously, Azure Search saves you a few nights in the office. And here’s how:

In Azure Search, there’s a concept of facets (originally coming from Elastic Search). When you query a specific index, the query syntax allows you to send along a facet parameter called facet where you can specify a list of fields within the index you’re querying which you want to get the facets on. For example, when using the Getting Started examples of the Azure Search Client Library, if you specify a HTTP parameter named facet and send its value as date (&facet=date), you’ll get back an array of possible values for the date facet, each containing also the count of documents within the index:

“@search.facets”:{“date@odata.type”:”#Collection(Microsoft.Azure.Search.V2014_10_20_Preview.QueryResultFacet)”,”date”:[{“count”:28,”value”:”2014-09-03T17:00:00Z”},{“count”:7,”value”:”2015-06-30T17:00:00Z”},{“count”:7,”value”:”2015-06-20T17:00:00Z”},{“count”:7,”value”:”2015-06-11T17:00:00Z”},{“count”:7,”value”:”2015-05-31T17:00:00Z”},{“count”:7,”value”:”2015-05-21T17:00:00Z”},{“count”:7,”value”:”2015-05-11T17:00:00Z”},{“count”:7,”value”:”2015-04-28T17:00:00Z”},{“count”:7,”value”:”2015-04-18T17:00:00Z”},{“count”:7,”value”:”2015-04-10T17:00:00Z”}]

facets_query

Facet result using Fiddler

Moreover, you also have the option of querying Azure Search using multiple facets at the same time by simply sending you the &facet HTTP parameter several times. For example, in this query I’m requesting filters on both the date and rating fields of the ‘events’ index:

https://alex.search.windows.net/indexes/events/docs?searchFields=description&$top=10&$count=true&facet=date&facet=rating&api-version=2014-10-20-Preview.

Additionally,  should you not want to show too many filtering options on your web page based on a single document field, you could send the count option to the facet HTTP parameter, like this:

https://alex.search.windows.net/indexes/events/docs?searchFields=description&$top=10&$count=true&facet=rating,count:3,sort:count&api-version=2014-10-20-Preview

In the previous example, I’ve instructed Azure Search to return only the 3 top filters of the rating field, ordered by the count of the filters in ascending order. If you want the same filters as result in descending order, all you have to do is send out the option as -count and you’re done. Additionally, you can also sort by value in both ascending and descending order by using the value, -value respectively value of the sort option.

Note that all the options for the facet parameter always have a name:value syntax.

The example so far have mostly been about getting back filters of single values (where a document field’s value is either ‘A’, ‘B’, ‘C’ etc. and return the filters based on these values). But what about dynamic filters, such as when you want to return ranges of values your documents fields’ contain, such as prices between $0-$100, $100-$500 and above $500? Well, welcome to range-facets! Azure Search allows you to send out a list of dynamic values which will act as range separators for your dynamic ranges. Specifically, the next example well return filters based on an event’s rating in the form of the ranges I’ve defined using the list of separators {5, 8}:

https://alex.search.windows.net/indexes/events/docs?searchFields=description&$top=10&$count=true&facet=rating,values:5%7C8&api-version=2014-10-20-Preview

Facet result using Fiddler

Facet result using Fiddler

 

If you’re using a .NET based language, the use of facets and Azure Search is even simple, because Azure Search Client Library comes with full support for Azure Search facets (as a matter of fact, Azure Search Client Library is the only Azure Search API to offer full support for facets by the time of this writing – and in full support, I mean using both static and range facets, sorting facets etc.)

Within C#, you could simply specify a list of Facet objects in the QueryParameters object you’re sending as a parameter to the QueryAsync method you’re calling on your index, like this:

var res = await this._AzureSearchService.Indexes[searchIndex].QueryAsync(new QueryParameters()
{
    QueryText = searchText,
    Facets = new List() { new Facet("rating"), new Facet("date") }
});

You can also send out a few options to the Facet constructor, so if you want to get only the first 5 elements based on their count result, you could call the QueryAsync method with a parameter similar to the one in the following example:

var res = await this._AzureSearchService.Indexes[searchIndex].QueryAsync(new QueryParameters()
{
    QueryText = searchText,
    Facets = new List() { new Facet("rating", 5, SortOrders.Ascending) }
});

Last but not least, getting back range facets can be done by specifying the list of range separators to your Facet object. The following example requests a range on the rating field with the 5 and 8 values as range separators, just like in one of the HTTP requests posted as an example previously:

var res = await this._AzureSearchService.Indexes[searchIndex].QueryAsync(new QueryParameters()
{
    QueryText = searchText,
    Facets = new List() { new Facet("rating", new List { 5, 8 }) }
});

It’s obvious that using facets within Azure Search Client Library is super easy and thanks to Azure Search, getting these dynamic filters on a search results page saves you a lot of time.

Note: Azure Search facet support is only available with version 0.7 and higher

 

 

2 Thoughts on “What Is A Facet?

  1. Pingback: Introducción a Azure Search - primera parte - Twisting code

  2. Pingback: penny skateboard buy

Leave a Reply

Post Navigation