- 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 Location private TaxonomyWebTaggingControl termPicker; //Button to search. private Button findButton; //Label Control for results private System.Web.UI.WebControls.Label result; //Taxonomy Field for Location private TaxonomyField location; //Data Grid to display Data private DataGrid dataGrid;
-
Add your CreateChildControls() method.
protected override void CreateChildControls() { try { //Obtain location Field as it is list. location = SPContext.Current.Web.Lists.TryGetList("Managed Metadata Demo").Fields["Location"] as TaxonomyField; //If was site Column. //location = SPContext.Current.Site.RootWeb.Fields["Location"] as TaxonomyField; //If location found. if (location != null) { //Create Picker. termPicker = new TaxonomyWebTaggingControl(); //Grab SspID termPicker.SspId.Add(location.SspId); //Grab TermSetId termPicker.TermSetId.Add(location.TermSetId); termPicker.AllowFillIn = false; termPicker.IsMulti = false; //Set Width. termPicker.Width = 200; //Add Control this.Controls.Add(termPicker); this.Controls.Add(new LiteralControl("<br/>")); //Add Button. findButton = new Button(); findButton.Text = "Search"; findButton.Click += new EventHandler(findButton_Click); this.Controls.Add(findButton); //Add results label this.Controls.Add(new LiteralControl("<br/>")); result = new System.Web.UI.WebControls.Label(); this.Controls.Add(result); this.Controls.Add(new LiteralControl("<br/>")); //Add DataGrid. dataGrid = new DataGrid(); this.Controls.Add(dataGrid); } else { //Throw Error message Controls.Add(new LiteralControl("Unable to find field Location.")); } } catch (Exception ex) { //Throw Error message Controls.Add(new LiteralControl("There was an error. " + ex.ToString())); } }
- Now the method for findButton_Click
void findButton_Click(object sender, EventArgs e) { result.Text = ""; //This returns as Name|GUID; string selectedTermValue = termPicker.Text; int seperatorIndex = selectedTermValue.IndexOf("|"); if (selectedTermValue != string.Empty && seperatorIndex != -1) { //Get the TermID. Guid termId = new Guid(selectedTermValue.Substring(seperatorIndex + 1)); //Get a TaxonomySession. TaxonomySession session = new TaxonomySession(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 results result.Text += "\n Sorry. No results could be found."; } } else { //Unable to find default keyword. throw new Exception(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> private void FillDataGrid(int[] wssIds) { //using System.Text; StringBuilder values = new StringBuilder(); //Loop through ID's and create CAML QUERY loop. for (int i = 0; i < wssIds.Length; i++) { values.Append("<Value Type=\"Integer\">"); values.Append(wssIds[i].ToString()); values.Append("</Value>"); } //Complete the CAML Query String. string strQuery = String.Format("<Where><In><FieldRef Name=\"Location\" LookupId=\"TRUE\"/><Values>{0}</Values></In></Where>", values.ToString()); //Get List SPList list = SPContext.Current.Web.Lists.TryGetList("Managed Metadata Demo"); if (list != null) { SPQuery query = new SPQuery(); query.Query = strQuery; //View Fields query.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 will get a result set of all documents tagged with Europe or within the Term children. Also note the query actually being called in the 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.
-