This is part III in my series about using TaxonomyFields in SharePoint 2010. In this part I will talk about how to search TaxonomyFields. I will show how to set up the metadata properties and how to search TaxonomyFields programmatically. This post continues on my previous posts about this subject:
Introduction
Part I: Declaration and initialization
Part II: Using taxonomyfields programmatically
Part III: Searching taxonomy fields (you are reading it!)
Managed Properties
To use our taxonomyfields in SharePoint search they need to be available in the managed properties of the farm. This works a little bit different with TaxonomyFields than with other fieldtypes. In this example I use the custom contenttype created in part I of this series and make the contained TaxonomyField “My taxonomy field” searchable using SharePoint search.
First I create a list named TaxonomyList and bind the custom contenttype “MyCustomContentType” to the list. The following image shows the list settings of the created list:

Then I add a new item to the list and fill the TaxonomyField with a value. Don’t forget this step! This is necessary for the crawler to pick up the taxonomyfield. For SharePoint to create a crawled property, the field must contain a value when a full crawl is started.

When the item is added I start a full crawl. To do this go to Central Administration –> Manage Service Applications –> Enterprise Search Service Application. Then go to Content Sources and start a full crawl on the correct content source. I usually create a new content source containing only my demo-site so the crawl doesn’t take too long.

And now….we wait…
What happens now is that the crawler indexes the webapplication, including our new item containing the TaxonomyField. It then creates a Crawled Property for our TaxonomyField. A crawled property is created for all the fields containing a value within the crawled webapplication. The magic of it is that in case of TaxonomyFields a Managed Property is also automatically created which is mapped to the crawled property. These mapped taxonomyfields allways have the prefix owstaxId. The corresponding crawled properties have the prefiex ows_taxId_. We can see this in the “Metadata Properties” section of the Enterprise Search Service Application.

The properties screen for this Managed Property looks like this:

Now we are finally ready to do some coding! In the next section I will create a webpart that uses code to find items using the custom taxonomy field.
NOTE: All of the above can be achieved using PowerShell, and you should use PowerShell to create managed and crawled properties when deploying real-life SharePoint solutions for customers as part of your deployment script. Check out this link for PowerShell cmdlets regarding Sharepoint Search: SP2010 PowerShell Commandlets on Technet
TIP: To test search queries there is a cool tool available from codeplex here: http://sharepointsearchserv.codeplex.com/
Searching a TaxonomyField from code
In this example I will create a very basic WebPart that gets data from a site using the search API. It will use the TaxonomyField I´ve created in this and the previous parts of this series in the WHERE clause of the search query. In this example I use the FullTextSqlQuery class to search the site.
To do this, first I add a visual webpart to my Visual Studio solution. In the .asx file I declare a basic DataView control to which I will databind my searchresults to make them visible on screen:
<asp:GridView ID="gvSearchResult" runat="server"></asp:GridView>
Then, in the codebehind I get the data from my site using the FullTextSqlQuery class and databind it to the grid:
Update 4th of November 2011: Be sure to read my follow-up post to learn how to improve this code to make it ready for a production environment!
/// <summary>
/// Binds the data to the grid
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Page_Load(object sender, EventArgs e)
{
gvSearchResult.DataSource = getData();
gvSearchResult.DataBind();
}
/// <summary>
/// Searches for items containing a Term
/// </summary>
/// <returns></returns>
private DataTable getData()
{
DataTable dt = new DataTable();
FullTextSqlQuery ftsq = new FullTextSqlQuery(SPContext.Current.Site);
ftsq.QueryText = " SELECT Size, Rank, Path, Title, Description, Write FROM Scope() " +
string.Format("WHERE ( (\"SCOPE\" = 'All Sites') ) AND " +
"owstaxIdMyTaxonomyField = '#0{0}' ORDER BY \"Rank\" DESC",
GetTermGuidByTitle("Investment Services"));
ftsq.ResultTypes = ResultType.RelevantResults;
ResultTableCollection rtc = ftsq.Execute();
if (rtc.Count > 0)
{
ResultTable relevantResults = rtc[ResultType.RelevantResults];
dt.Load(relevantResults, LoadOption.OverwriteChanges);
}
return dt;
}
/// <summary>
/// Basic method to find a term. Of course this method needs improvement
/// and is here for illustrational purposes only.
/// DO NOT USE IN A PRODUCTION ENVIRONMENT
/// </summary>
/// <param name="title"></param>
/// <returns></returns>
private Guid GetTermGuidByTitle(string title)
{
// Open a taxonomysession and get the associated termstore from it
TaxonomySession session = new TaxonomySession(SPContext.Current.Site);
TermStore termStore = session.TermStores[0];
Term term = termStore.GetTerms(title, true)[0];
if (term != null)
return term.Id;
else throw new Exception("Term not found");
}
You need to add a reference to the Microsoft.Office.Server.Search dll to make this code work.
In the code I am searching the Managed Property called owstaxIdMyTaxonomyField for the value
“Investment Services”. As you can see the query executed by the FullTextSqlQuery class looks as follows:
ftsq.QueryText = " SELECT Size, Rank, Path, Title, Description, Write FROM Scope() " +
string.Format("WHERE ( (\"SCOPE\" = 'All Sites') ) AND " +
"owstaxIdMyTaxonomyField = '#0{0}' ORDER BY \"Rank\" DESC",
GetTermGuidByTitle("Investment Services"));
The guid of the term I’m looking for is preceded by “#0”. This means that I want to search for the exact term. If you are searching for the term or any term below it in the termstore hierarchy prefix the guid with “#”.
NOTE: The GetTermGuidByTitle private method is just a quick way for me to get a term from the termstore. It is only printed here to show you a complete, working peace of code. If you want to look up a term from the termstore do it in a more robust way. In The 2nd part of this series I talk about how to programmatically lookup values from the termstore.