Tuesday, December 13, 2011

Returning Best Bets and Visual Best Bets with KeywordQuery and FAST Search for SharePoint

When using the Search Center the Best Bets or Visual Best Bets functionality works like a charm, but I have not been able to get it to work using the KeywordQuery class in SharePoint.

I had done some research previously on the matter after being contacted by Xavier Vanneste who blogged about this (http://blog.xvanneste.com/Lists/Billets/Post.aspx?ID=82), but was not able to figure it out at the time.

I’m currently writing sample code for my upcoming book on FS4SP and I had to figure this out. Time to bring out the tools!

One hour with the Visual Studio Reflector plugin and setting break-points internally in the SSA I finally figured it out. And in a way it was obvious.


All keyword settings with FAST requires a Search Setting Group and you will have one group for each site collection in your SharePoint farm. The ID of the search setting group is the GUID of the site collection. And this ID is the solution.

KeywordQuery has a property named “UserContextGroupID”, and MSDN states:
Gets or sets the identifier used to group keywords used for matching best bets and visual best bets. This property specifies an identifier used to group keywords used for matching best bets and visual best bets.
By assigning the UserContextGroupID property and requesting to get back SpecialTermResults it is now working like a charm.

Here’s a small sample which will return a Visual Best Bet assigned to the term “FAST Search for SharePoint”.

var searchProxy = (SearchServiceApplicationProxy)SearchServiceApplicationProxy.GetProxy(SPServiceContext.Current);
KeywordQuery kq = new KeywordQuery(searchProxy);
kq.QueryText = "FAST Search for SharePoint";
kq.ResultsProvider = SearchProvider.FASTSearch;

// specify best bets/visual best bets
kq.ResultTypes = ResultType.SpecialTermResults;
// specify the Search Settings Group ID
kq.UserContextGroupID = SPContext.Current.Site.ID.ToString();

ResultTableCollection resultTableCollection = kq.Execute();
ResultTable visualBestBetsTable = resultTableCollection[ResultType.VisualBestBetsResults];
foreach (DataRow row in visualBestBetsTable.Table.Rows)
{
    string name = (string)row["Name"];
    string uri = (string)row["Uri"];
    string description = (string)row["Description"];
    string keyword = (string)row["Keyword"];
    string teaser = (string)row["Teaser"];
    string contentType = (string)row["TeaserContentType"];
}