SharePoint Tag Cloud using Deep refiners in Fast Search

SharePoint 2010 offers good enhancements and capabilities over the previous versions. If you exploit them wisely you can produce great solutions.

Recently, I wanted to have a Tag cloud to show the most heavily used tagskeywords in the pages. The important part of the requirement is that the Tag Cloud should provide aggregate view of the tags applied to pages at different scopes like:

  • All sites in a Site Collection
  • All site collections in a Web Application
  • All Web applications in a Farm

Also, the tags should be hyperlinks which would take user to page with list of all pages with similar tags.

I thought to use Managed Metadata feature of SharePoint 2010 that provides efficient way to manage Tags. However, later I discovered that the Tag cloud web part provided by SharePoint 2010 can only be used for Social Tags and not for Managed Metadata columns.

I also found a Tag cloud at Codeplex that uses Managed Metadata: http://metadatawebpart.codeplex.com/ . However this web part is not able to meet all of my requirements.

After exploring all the available options, I decided to design my own solution to meet all of the above requirements.

The solution is based on Deep Refiners in Fast Search.

FAST Search provides the capability of result refining on metadata associated with all results.
Moreover, FAST Search shows counts for each of the refiners.

The Refinement is also available in SharePoint 2010 Search with the capability of refining results by the most important metadata. However, only FAST Search provides the capability of result refining on metadata associated with all results  called Deep Refinement.

Below is a screenshot showcasing deep refiners showing facets for all items found in search:

FAST Search Deep Refiners

FAST Search Deep Refiners

So, the Refinement panel on a Fast Search results page, more or less, acts like a Tag cloud.

However, you cannot use the panel as standalone web part since it works in collaboration with other Search web parts. So there is need to programmatically access the get the deep refiners and display them as Tags where the font size or weight of a tag in is determined by its refinement count.

Before we access the deep refiners in code, There are some prerequisite steps to follow :

Note : You should have Fast Search installed and configured with Search Service applications running.

1 . Create Managed Property in Fast Search Administration that maps the Managed Metadata column (It can be any other type of column as well if you want. I used Managed Metadata as it provides auto fill and more control on tags)

2. Set a managed property as  deep refiner: You can do it via PowerShell or Fast Search Administration UI.

For PowerShell, here are the details.

For UI, You can do it via ‘Fast Query Service Application’ management interface as below:

Fast Search Managed Property

Fast Search Managed Property

3. Do a Full Crawl.

Now we are ready to get refiners in code. We can use Keyword query class like I have demonstrated in another post with some changes as below :

1. Set the result provider to Fast Search

 keywordQuery.ResultsProvider = SearchProvider.FASTSearch;

2. Specify the refiners using KeyworQuery.Refiners property

//Tags is the name of the managed property mapped to managed metadata column
keywordQuery.Refiners = "Tags";

This property is used to set the set of refiners to be returned in a search result. The value for each refiner is a format string that specifies the name of a refiner and optionally a set of refinement options for this refiner. No refiners will be returned with the query result if the Refiners property is empty.

3. Specify that the results set should contain refined results matching the search query.

keywordQuery.ResultTypes = ResultType.RefinementResults;

4. Specify a query to search all items. The below query look for all list items. You can provide custom query to restrict the scope of search.

keywordQuery.QueryText = "contentclass:STS_ListItem";

Below is the complete code that you can use in a console application to test the result :

using (SPSite site = new SPSite("http://sp2010site"))
            {
                SearchServiceApplicationProxy SSAProxy = (SearchServiceApplicationProxy)SearchServiceApplicationProxy. GetProxy(SPServiceContext.GetContext(site));
                KeywordQuery keywordQuery = new KeywordQuery(SSAProxy);       
                keywordQuery.ResultsProvider = SearchProvider.FASTSearch;
                keywordQuery.QueryText = "contentclass:STS_ListItem";
                keywordQuery.ResultTypes = ResultType.RefinementResults;            
                keywordQuery.EnableFQL = false;
                keywordQuery.StartRow = 0;
                keywordQuery.RowLimit = 100000;
                keywordQuery.KeywordInclusion = KeywordInclusion.AllKeywords;
                keywordQuery.Refiners = "Tags";
                ResultTableCollection searchResults = keywordQuery.Execute();
                if (searchResults.Exists(ResultType.RefinementResults))
                {
                    ResultTable searchResult = searchResults[ResultType.RefinementResults];
                    Console.WriteLine(searchResult.TotalRows);
                    DataTable result = new DataTable();
                    result.TableName = "SearchResults";
                    result.Load(searchResult, LoadOption.OverwriteChanges);
                    DataSet ds = new DataSet();
                    ds.Tables.Add(result);
                    XmlDocument xmlDoc = new XmlDocument();
                    xmlDoc.LoadXml(ds.GetXml());
                    XmlNodeList nodeList = xmlDoc.DocumentElement.SelectNodes("/NewDataSet/SearchResults[RefinerName='tags']");                   
                    foreach (XmlNode myNode in nodeList)
                    {
                        if (myNode != null)
                            Console.WriteLine(myNode.SelectSingleNode("RefinementName").InnerText + "(" + myNode.SelectSingleNode                            ("RefinementCount").InnerText+")");
                    }
                    Console.Read();

In above code, The RefinementName gives you the value of tag and RefinementCount gives you the count i.e. how many times the tag is used

Below is the output in console application :

Tag Cloud in Console

Tag Cloud in Console

 

Now, you can transform the above code to a webpart.

You can decide on font size of a tag based on the RefinementCount : Greater RefinementCount , higher the font size. You can also use below formula to calculate font size on fly :

s_i = left lceil frac{f_{mathrm{max}}cdot(t_i - t_{mathrm{min}})}{t_{mathrm{max}}-t_{mathrm{min}}} right rceil for t_i > t_{mathrm{min}}; else s_{i}=1

  • s_i: display fontsize
  • f_{mathrm{max}}: max. fontsize
  • t_i: count
  • t_{mathrm{min}}: min. count
  • t_{mathrm{max}}: max. count

Now, You need to link the Tag to the page which has a list of pages with similar tag. You can use out of box search page for this or again build your own with a webpart using Keyword query.

In a tag cloud,  you can dynamically create  link for  Tags like below :

<a href="/search.aspx?k=Tags:Microsoft"><font size=15>Microsoft<font></a>,<a href="/search.aspx?k=Tags:Yahoo"><font size=12>Yahoo<font></a>

When a user click the Tag  named “Microsoft” for example , the search page will present results with Keyword Query “Tags:Microsoft”  i.e. All pages or list items tagged with keyword “Microsoft”.

So, you have a Tag cloud which you can fine tune according to your need. The use of  Search to find Tags provides good performance even if you aggregate huge data .

Enjoy!

No Responses to “SharePoint Tag Cloud using Deep refiners in Fast Search”

Leave a Reply

Subscribe

Get every post delivered to your inbox via FeedBurner :

© 2010-2013 Extreme Sharepoint | The content is copyrighted to Amit Kumawat and may not be reproduced on other websites.