Retrieving the Best Bets for SharePoint search programmatically based on a Search query

I have got a requirement to develop a Best Bets web part for SharePoint People Search as the default Search Best Bets does not work for People search. Well, will update on that later.

When I was looking for code on how to read the Best bets for a site programmatically I got it from this blog post. In this post I have enhanced that coding in order to filter the best bets collection by keywords term and synonyms term based on a search query using LINQ queries. Explanations are given in comments.

You need to have these 2 namespaces for LINQ query and IEnumerable collection that we are going to use.

using System.Linq;
using System.Collections.Generic;

Here is the complete code.

using (SPSite site = new SPSite("http://SharePointSite/"))
            {
                // get the proxy for the search service application
                    SearchServiceApplicationProxy proxy = (SearchServiceApplicationProxy)SearchServiceApplicationProxy.
       GetProxy(SPServiceContext.GetContext(site));

                //get the Keywords collection for the site
                    Keywords keywords = new Keywords(proxy, new Uri(site.Url));

                //filter the keywords collection with Linq query and store it in an IEnumerable collection
                    IEnumerable<Keyword> Keywords = from Keyword keyword in keywords.AllKeywords
                                                    where keyword.Term.ToLower() == srchQuery.ToLower()  //checking for the terms equal to the search query
                                                    ||
                                                    (from Synonym c in keyword.Synonyms
                                                     where c.Term.ToLower() == srchQuery.ToLower()  // checking if synonyms are present for the search query
                                                     select c).Count() > 0

                                                    select keyword;

                    // loop through each keyword from the above collection
                    foreach (Keyword keyword in Keywords)
                    {
                        Console.WriteLine(keyword.Term);
                        foreach (BestBet bet in keyword.BestBets)
                        {
                            Console.WriteLine("\t{0} ({1})", bet.Title, bet.Url);
                        }
                    }
                }

Error occurred in deployment step ‘Activate Features’: Object reference not set to an instance of an object.

Do you get this error while deploying solution with a Feature Event Receiver through Visual Studio 2010. Well, I did while deploying a custom timer job solution which has a feature receiver to activate and deactivate the timer job feature.

Untitled

All I did immediately was that started googling as usual :D. Somewhere I got to know this error occurs if we have used SPContext class in our feature activate event receiver. But, when I checked my event receiver I did not use this class at all.

Then, I attached the solution to OWSTimer.exe and started debugging to trace the error. I then found that I have accessed the SPSite of the feature as its parent as shown below.

Untitled

And the scope of the feature was “Web” as shown below.

Untitled

The Parent property of a feature represents the object that represents the scope of the feature. So, in my case I have assigned the Parent property of the feature (Which is  SPWeb object) to the SPSite object instead and thus the mismatch caused the error while deploying. I know that this is not a very intellectually found fix, but still there could be few people like me who would immediately start googling for a solution :D.

Comparing two Fields of a SharePoint list

This topic is not something new in my blog, as I have blogged about this before too, thought not exclusively on this topic.

In many of my previous projects I had this task of retrieving list items from a SPList by comparing two columns in it. I found that CAML queries do not have the functionality to compare two columns. So, immediately I started to Google to find a solution :D.

I found that we can achieve this using LINQ Queries on SPListItemCollection as well as LINQ to SharePoint provider.

Let us first see a sample query using LINQ on SPListItemCollection:
Untitled

In the above LINQ query we are comparing 2 Number type columns of a SharePoint list by using the OfType filter on SPListItem. You can see that we are accessing the column values of a SPListItem in an usual conventional way by putting the column names in double quotes and also by converting them into a double.

Now let us see how to do the same thing using LINQ to SharePoint. I’m not going to explain how to use LINQ to SharePoint provider. There is a very good example provided here which clearly explains the process.

Here is a LINQ query formed using LINQ to SharePoint provider to compare two columns of a SharePoint list.

Untitled

As you can see in the above query we are comparing the two columns of a SharePoint list using strongly typed name of them because of which there won’t be any spelling mistakes on column names and also we need not do any typecasting as we did in the previous method.

But there is also a disadvantage of using LINQ to SharePoint provider. We do not have access to few default columns like Modified by, Created by, Author & so on.