Search CAML query with Managed Metadata
- Part 1 – Setting up Managed Metadata Service
- Part 2 – Explaining how to use the Term Store
- Part 3 – Creating a Site Column with managed Metadata (gotchas with List Definitions)
- Part 4 – Search Refiners with Managed Metadata
- Part 5 – Search CAML query with Managed Metadata
- Update – Creating a Site Column with Managed Metadata using Javascript.
In this final blog of this series, I will show you how to perform a CAML Query against a list for Managed Metadata Column. Now I’ve realized over the past week while I’ve been writing these blogs, that you might assume that I’d be using the Search Engine to obtain my results. Actually I’m performing a SPQuery on a SPList. (Perhaps I will create an additional post later how to actually “Search” via code.
The trick with performing a CAML query again a list for Managed Metadata is using <In> and listing every wssIds for the main term, and all its children. Normally when you perform a CAML query you would enter something similar to the following
<Where><Eq><FieldRef Name="Title"/><Value>File</Value></Eq></Where> |
If you performed the above on a Managed Metadata column it would only bring back the one value, not the children.
If you remember from my last blog, the Managed Metadata column was called Location. It was Term Set based on Continents and the Countries within them. So to perform a query of Europe and all its child terms, you would first need to get the ID of the Term “Europe” then get all the children ID terms (e.g, Albania, Andorra, Anguilla etc).

Once we have the ID’s you then perform a CAML query similar to below.
<Where><In><FieldRef Name="Location" LookupId="TRUE"><Values><Value Type="Integer">13</Value><Value Type="Integer">3</Value><Value Type="Integer">9</Value></Values></In></Where> |
Basic WebPart with Taxonomy Picker performing a CAML Query.
I’m going to walk through the steps that will allow you to obtain the Metadata Term, and then obtain all the children, before performing a query on a list. My list is called managed Metadata Demo, and I have a Managed Metadata Column on the list called Location.


- Create an Empty SharePoint project. Make it a Farm Solution, and point to your SharePoint site with your document library containing your Managed Metadata column.
- Add the following References Microsoft.SharePoint.Taxonomy.
- Right click the project and select Add >New Item
- From the Add New Item dialog, select Web Part. (Not Visual Web Part)
I called my Web Part WPFilter. - Add the Using statement using Microsoft.SharePoint.Taxonomy; to the top of the c# class WPFilter.
- Add the following private variables.
//Control for user to pick a LocationprivateTaxonomyWebTaggingControl termPicker;//Button to search.privateButton findButton;//Label Control for resultsprivateSystem.Web.UI.WebControls.Label result;//Taxonomy Field for LocationprivateTaxonomyField location;//Data Grid to display DataprivateDataGrid dataGrid;- Add your CreateChildControls() method.
protectedoverridevoidCreateChildControls(){try{//Obtain location Field as it is list.location = SPContext.Current.Web.Lists.TryGetList("Managed Metadata Demo").Fields["Location"]asTaxonomyField;//If was site Column.//location = SPContext.Current.Site.RootWeb.Fields["Location"] as TaxonomyField;//If location found.if(location !=null){//Create Picker.termPicker =newTaxonomyWebTaggingControl();//Grab SspIDtermPicker.SspId.Add(location.SspId);//Grab TermSetIdtermPicker.TermSetId.Add(location.TermSetId);termPicker.AllowFillIn =false;termPicker.IsMulti =false;//Set Width.termPicker.Width = 200;//Add Controlthis.Controls.Add(termPicker);this.Controls.Add(newLiteralControl("<br/>"));//Add Button.findButton =newButton();findButton.Text ="Search";findButton.Click +=newEventHandler(findButton_Click);this.Controls.Add(findButton);//Add results labelthis.Controls.Add(newLiteralControl("<br/>"));result =newSystem.Web.UI.WebControls.Label();this.Controls.Add(result);this.Controls.Add(newLiteralControl("<br/>"));//Add DataGrid.dataGrid =newDataGrid();this.Controls.Add(dataGrid);}else{//Throw Error messageControls.Add(newLiteralControl("Unable to find field Location."));}}catch(Exception ex){//Throw Error messageControls.Add(newLiteralControl("There was an error. "+ ex.ToString()));}}- Now the method for findButton_Click
voidfindButton_Click(objectsender, EventArgs e){result.Text ="";//This returns as Name|GUID;stringselectedTermValue = termPicker.Text;intseperatorIndex = selectedTermValue.IndexOf("|");if(selectedTermValue !=string.Empty && seperatorIndex != -1){//Get the TermID.Guid termId =newGuid(selectedTermValue.Substring(seperatorIndex + 1));//Get a TaxonomySession.TaxonomySession session =newTaxonomySession(SPContext.Current.Site);if(session.DefaultKeywordsTermStore !=null){//get the default metadata service application/*Function GetWssIdsOfTerm* Site - The SPSite object that cotains the taxonomy hidden list.* termStoreId - A Guid object that uniquely identifies the TermStore object* termSetId - A Guid object that uniquely identifies the TermSet Object* termId - A Guid object that uniquely identifies the Term* includeDecendants - A boolean value that must be set to true if you would like the list of* item Ids of descendant Term Obejct to also be included in the results.* limit - The maximum number of list items IDs to return.**/int[] wssIds = TaxonomyField.GetWssIdsOfTerm(SPContext.Current.Site, session.DefaultKeywordsTermStore.Id, location.TermSetId, termId,true, 100);if(wssIds.Length > 0){//Pass to SPQuery and display results.FillDataGrid(wssIds);}else{//No resultsresult.Text +="\n Sorry. No results could be found.";}}else{//Unable to find default keyword.thrownewException(string.Format("DefaultKeyWordTermStore not found in this site {0]", SPContext.Current.Site.Url));}}}<ul><li><div>Finally add the code to grab the CAML query, perform it, and add the results to the data grid.</div>privatevoidFillDataGrid(int[] wssIds){//using System.Text;StringBuilder values =newStringBuilder();//Loop through ID's and create CAML QUERY loop.for(inti = 0; i < wssIds.Length; i++){values.Append("<Value Type=\"Integer\">");values.Append(wssIds[i].ToString());values.Append("</Value>");}//Complete the CAML Query String.stringstrQuery = String.Format("<Where><In><FieldRef Name=\"Location\" LookupId=\"TRUE\"/><Values>{0}</Values></In></Where>", values.ToString());//Get ListSPList list = SPContext.Current.Web.Lists.TryGetList("Managed Metadata Demo");if(list !=null){SPQuery query =newSPQuery();query.Query = strQuery;//View Fieldsquery.ViewFields ="<FieldRef Name='FileLeafRef' /><FieldRef Name='Title'/><FieldRef Name='Location'/>";SPListItemCollection items = list.GetItems(query);//Results of Query to show User Query made.result.Text = System.Web.HttpUtility.HtmlEncode(strQuery);if(items.Count < 1)result.Text +="\n Sorry. No results could be found.";//Add to grid and bind.dataGrid.DataSource = items.GetDataTable();dataGrid.DataBind();}else{result.Text ="Sorry. Unable to find the list Managed Metadata Demo";}}[/soucecode]</li><li><div>Now run your code. Add your web part to a page. It should look similar to below.</div><img alt=""src="https://cann0nf0dder.files.wordpress.com/2013/04/041013_2046_searchcamlq3.png"/></li><li><div>If I enter Europe, or use the label picker to find Europe and click Search, I willgeta resultsetof all documents tagged with Europe or within the Term children. Also note the query actually being calledinthe result label.</div><Where><In><FieldRef Name="Location"LookupId="TRUE"/><Values><Value Type="Integer">13</Value><Value Type="Integer">1</Value><Value Type="Integer">2</Value><Value Type="Integer">3</Value><Value Type="Integer">8</Value></Values></In></Where>
- As you can see from the results above, it has returned United Kingdom, Switzerland, Turkey and Europe documents. Hopefully you would you a ListViewByQuery webpart or display your data a little better than this.
This concludes my Managed Metadata Series. Hope you have learnt something new. I’m hoping to write a bonus post on this series that will actually perform a Search query on Managed Metadata.