With the release of SharePoint 2013, a lot has changed with
the way things were being implemented. For instance, till SP 2010, it was
possible to use FullTextSQLQuery to query the results obtained from SharePoint
Search Crawls. It was much easier to use considering its syntax was similar to
SQL.
Now, in SP 2013, it has been deprecated. There is not even a
provision to support backward compatibility FullTextSQLQuery on SharePoint 2013
platform. The only place we developers can now resort to is the KeywordQuery. It
can be implemented in the pretty much same way as it was implemented on SP
2010.
So, let me take this opportunity to shed some light on
Keyword Query and how it can be used to query crawl results.
KeywordQuery supports two syntax for query string formation –
- Keyword Query Language (KQL) and
- FAST Query Language (FQL)
KQL is the default syntax which can be used. FQL needs to be
explicitly enabled to use it. Following is the sample code which showcases both
these approaches –
Approach 1 –
KeywordQuery using KQL
static void Main(string[] args)
{
SPSite
site = new SPSite("url_whose_results_you_wish_to_query");
SearchServiceApplicationProxy proxy =
(SearchServiceApplicationProxy)SearchServiceApplicationProxy.GetProxy(SPServiceContext.GetContext(site));
using (KeywordQuery keywordQuery = new KeywordQuery(proxy))
{
keywordQuery.ResultsProvider = SearchProvider.Default;
keywordQuery.StartRow = 0;
keywordQuery.RowLimit = 500;
keywordQuery.EnableStemming = true;
keywordQuery.TrimDuplicates = false;
keywordQuery.AuthenticationType = QueryAuthenticationType.PluggableAuthenticatedQuery;
keywordQuery.Culture = CultureInfo.CurrentCulture;
keywordQuery.KeywordInclusion = KeywordInclusion.AllKeywords;
keywordQuery.QueryText = "scope:\"All Sites\" AND
(contentclass:\"STS_Site\" OR
contentclass:\"STS_Web\")";
keywordQuery.SelectProperties.Add("path");
keywordQuery.SelectProperties.Add("title");
keywordQuery.SelectProperties.Add("contentclass");
SearchExecutor executor = new SearchExecutor();
ResultTableCollection resultTableCollection =
executor.ExecuteQuery(keywordQuery);
var resultTables = resultTableCollection.Filter("TableType",
KnownTableTypes.RelevantResults);
var resultTable = resultTables.FirstOrDefault();
}
}
In the above code snippet, note the SPSite URL which should
be URL of the site whose search results you wish to query.
In the previous version of SharePoint, RowLimit actually
had no limits. But in newer versions, it has the maximum limit of 500. This number
is however configurable if we run PowerShell script on the SharePoint Search
Service Application.
Also, note that now, we cannot directly execute the
Query. Earlier we would simply call the method
KeywordQuery.ExecuteQuery()
and it would fetch the results for us. Now, SP 2013
introduces a new class SearchExecutor specifically built to execute queries. So
in order to run a query, we would first have to initialize this class and then
call its ExecuteQuery method on our KeywordQuery.
ResultType class and its corresponding KeywordQuery.ResultType
property are also now obsolete. Instead we would now need to call a filter
method on our resultant collection to get our desired results (see the code
above).
Notice the query text in the above snippet. It is much
similar to what was used in SP 2010.
Another important thing to notice above is that we would
need to explicitly specify which columns should be returned in the query
result. Of course, it was done earlier and in much simpler fashion using
FullTextSQLQuery. Now, we would need to call the method –
keywordQuery.SelectProperties.Add("<column_name>")
to return this column in the result table collection.
Approach 2 –
KeywordQuery using FQL
static void Main(string[] args)
{
SPSite
site = new SPSite("<url_whose_results_you_wish_to_query>");
SearchServiceApplicationProxy proxy =
(SearchServiceApplicationProxy)SearchServiceApplicationProxy.GetProxy(SPServiceContext.GetContext(site));
using (KeywordQuery keywordQuery = new KeywordQuery(proxy))
{
keywordQuery.ResultsProvider =
SearchProvider.Default;
keywordQuery.SourceId = new
Guid("<RESULT_SOURCE_GUID>");
keywordQuery.EnableFQL = true;
keywordQuery.StartRow = 0;
keywordQuery.RowLimit = 500;
keywordQuery.EnableStemming = true;
keywordQuery.TrimDuplicates = false;
keywordQuery.AuthenticationType = QueryAuthenticationType.PluggableAuthenticatedQuery;
keywordQuery.Culture = CultureInfo.CurrentCulture;
keywordQuery.KeywordInclusion = KeywordInclusion.AllKeywords;
keywordQuery.QueryText = "and(scope:string(\"All
Sites\"), or(contentclass:string(\"STS_Site\") ,
contentclass:string(\"STS_Web\")))";
keywordQuery.QueryText = "and(scope:string(\"All
Sites\"), or(contentclass:STS_Site, contentclass:STS_Web))";
keywordQuery.SelectProperties.Add("path");
keywordQuery.SelectProperties.Add("title");
keywordQuery.SelectProperties.Add("contentclass");
SearchExecutor executor = new SearchExecutor();
ResultTableCollection resultTableCollection =
executor.ExecuteQuery(keywordQuery);
var resultTables = resultTableCollection.Filter("TableType",
KnownTableTypes.RelevantResults);
var resultTable = resultTables.FirstOrDefault();
}
}
Notice the highlighted lines of code in Cyan color in the above
snippet. Only those lines are different from what we saw earlier. Rest all
settings remain the same. in the above example, i have used two types of FQL queries. You can use either of them.
SourceID needs to be explicitly mentioned here because in
SharePoint 2013, we need to create a custom Result Source which possesses a
different query string in it. I would cover creating Result Sources in
SharePoint 2013 in a separate post.
Happy coding !!