EPiServerOctober 11, 2011

Would you like some business logic with that search?

Use the BoostMatching method to tune the ordering of search results according to business needs.

Following up on yesterdays post on the new highlighting features in the Truffler .NET API (introduced here) I thought I’d also introduce another new feature, which in my opinion just might be the coolest thing yet. Especially since it can enable us as developers to deliver some serious business value by implementing fine grained business logic. Meet the BoostMatching method.

Using the BoostMatching method we can boost search hits that match a certain criteria. That is, we can control the sorting when sorting by relevance. The criteria is expressed in a strongly typed way, just as if we were using the Filter method.

A business driven example

Imagine that we’re building a site for a car dealership. The business may then want to boost search hits for cars that are in stock a little.

var searchResult = client.Search<Car>()
    .For("Volvo")
    .BoostMatching(x => x.InStock.Match(true), 1.5)
    .GetResult();

Using the above code we execute a search for the search term “Volvo” and say that cars that are in stock should have 50% higher relevance than they otherwise would have. This doesn’t necessarily mean that all cars that are in stock will be sorted first, the relevance calculated for the search term is still a major factor, but we’re increasing the probability that a car in stock is sorted before one that isn’t a little.

As we’re able to use any filter expression we can use more complex conditions as well. For instance, if a car is in stock and there’s a new version of the same model coming soon, the car in stock will probably drop significantly in value. So selling it before that happens is important. Lets boost search hits for such cars a lot:

var searchResult = client.Search<Car>()
    .For("Volvo")
    .BoostMatching(x => x.InStock.Match(true), 1.5)
    .BoostMatching(x => 
        x.NewModelComingSoon.Match(true) 
        & x.InStock.Match(true), 5)
    .GetResult();

Let’s look at a more likeable example. Imagine we’re building a site where visitors can find restaurants. One might then do a search for Indian food with a simple query like this:

var searchResult = client.Search<Restaurant>()
    .For("Indian")
    .GetResult();

That’s great, but what if we know the locations of the restaurants and the visitor is browsing the site using a mobile phone or we have some other way to get his or hers location? Well, then we might just boost restaurants close to that location a lot, and those fairly close a little.

client.Search<Restaurant>()
    .For("Indian")
    .BoostMatching(x =>
        x.Location.WithinDistanceFrom(
            gpsPosition, 1.Kilometer()), 3)
    .BoostMatching(x =>
        x.Location.WithinDistanceFrom(
            gpsPosition, 3.Kilometers()), 1)
    .GetResult();

Of course even if we don’t know the visitors exact location we might still find an approximation by using an IP database and boost restaurants in a very wide radius to increase the probability of restaurants in the correct city being returned first. But what if the visitor is logged in and we know what part of the city he or she lives in? Given that we have mapped a number of coordinates describing that area (see an example of that here) we could boost restaurants in that area.

client.Search<Restaurant>()
    .For("Indian")
    .BoostMatching(x =>
        x.Location.Within(CoordinatesOf.Sodermalm), 2)
    .GetResult();

As always we're keen on feedback so if you don't like the naming or syntax of the BoostMatching method, or find it confusing and want more examples, please let us know!