Tuesday, 27 March 2012

Add Rating Stars to the Search Results

I Hope you found my previous article on Encoding and Decoding Refiner Values useful. In this article I will Explain to how to Add Rating Stars to the search results. Please let me know if you find any issues while implementing it.

Create a Custom List and Enable Rating on it

We will start with creating the list with some dummy columns and insert some data in it. I have created a 'Employee List' whose structure looks something like this

Now we need to enable the rating to the list. Click on the list settings from the ribbon under the 'List Tools' Group and 'List' tab
Now click on the 'Rating Settings' link under the 'General Settings' category.
Select 'Yes' under 'Allow items in this list to be rated?' and click 'Ok'.

This has successfully enabled ratings on the list and added following two columns required for rating to work.

Rating (0-5)   Rating (0-5)  
Number of Ratings   Number of Ratings 

If you go back to the list it would have added the Rating Column to the list.

Rate some Entries in the List and Run the Services for Rating

Now add rating to these entries. It wont be reflected immediately on the list, it will get updated once 'User Profile Service Application - Social Data Maintenance Job' and  
'User Profile Service Application - Social Rating Synchronization Job' jobs are executed.

This jobs are scheduled to run every hour (By default) by the sharepoint timer services. However we can change the frequency of the this jobs

Go to Central Administration -> Monitoring -> Timer Jobs -> Review job definitions

Scroll down to locate the above services

Click on each of the job and schedule it to run for every 1 min (Just so that we don't have to wait for our ratings to get updated, in normal scenario running every 

one hour is just fine !)

Once this jobs are executed successfully, the ratings that you entered previously would have started reflecting.

Start the Full Crawl of the site to Create Crawl Property

Now once we have to prepare our FAST search server to include the ratings in our search indexing.

So go to the crawled property categories and select 'Sharepoint' category. Now search for 'rating'

It should return following to crawled properties


If it does not return the above two crawled properties, You need to start full crawl of the site where your list is located.
Once the crawl is successfull, sharepoint will automatically create the above crawled properties

Create Managed Property for the Ratings

As we have the crawled property created we can create a managed property for each of them and map it to crawled property.

So you need to create following two managed property
a. Rating
b. RatingCount

Below are the details of the managed property that will help you to create a managed property.

Start the full crawl of the Site

After creating the managed property we need to full crawl the site 'AGAIN'. Yes, When we earlier crawled the site it just recognised that two more fields are available for crawling. But managed properties were not mapped so it didnt knew where to index the data.

so start the full crawl of the site, leave it as it is and proceed to the next step.

Modify Core Result Webpart and it's XSLT

Now we need to modify the search webpart of our site to display the rating stars in our search.

So go to your results.aspx and then edit the page. Now edit your core results webpart.

Under coreresultswebpart properties->Core Result -> Display Properties -> Fethced Properties
A. Include the following lines before the </Column> tag

<Column Name="Rating"/>
<Column Name="RatingCount"/>

B. Open the XSL Editor of the webpart by clicking on 'XSL Editor' button

Add the below lines of code after the Div tag of '<div class="srch-Title2">'

  <div class="srch-Description">
    <xsl:if test="rating &gt; 0">
        <xsl:call-template name="DisplayRating">
          <xsl:with-param name="theRating" select="rating" />
          <xsl:with-param name="theRatingCount" select="ratingcount" />
      <br />

C. Copy the following code before the </xsl:stylesheet> tag

<xsl:template name="DisplayRating">
  <xsl:param name="theRating"/>
  <xsl:param name="theRatingCount"/>
  <xsl:if test="$theRating > 0">
    <div style="display: inline-block; padding-left: 8px;">
        <xsl:variable name="tempTitle" select="concat($theRating, ' Stars (')"/>
        <xsl:variable name="tempTitle2" select="concat($theRatingCount, ' Ratings)')"/>
        <xsl:variable name="ratingTitle" select="concat($tempTitle, $tempTitle2)"/>

        <xsl:attribute name="title">
          <xsl:value-of select="$ratingTitle"/>
          <xsl:when test="round($theRating) = 0 and $theRating &gt; 0">
            <xsl:attribute name="style">background-image:url(/_layouts/images/Ratings.png);cursor:default;height:16px;margin:0px;background-repeat:no-repeat;background-position:-368px 0px;width:16px;</xsl:attribute>
          <xsl:when test="round($theRating) = 1 and round($theRating) &lt;= $theRating">
            <xsl:attribute name="style">background-image:url(/_layouts/images/Ratings.png);cursor:default;height:16px;margin:0px;background-repeat:no-repeat;background-position:-352px 0px;width:16px;</xsl:attribute>
          <xsl:when test="round($theRating) = 2 and round($theRating) &gt; $theRating">
            <xsl:attribute name="style">background-image:url(/_layouts/images/Ratings.png);cursor:default;height:16px;margin:0px;background-repeat:no-repeat;background-position:-352px 0px;width:32px;</xsl:attribute>
          <xsl:when test="round($theRating) = 2 and round($theRating) &lt;= $theRating">
            <xsl:attribute name="style">background-image:url(/_layouts/images/Ratings.png);cursor:default;height:16px;margin:0px;background-repeat:no-repeat;background-position:-336px 0px;width:32px;</xsl:attribute>
          <xsl:when test="round($theRating) = 3 and round($theRating) &gt; $theRating">
            <xsl:attribute name="style">background-image:url(/_layouts/images/Ratings.png);cursor:default;height:16px;margin:0px;background-repeat:no-repeat;background-position:-336px 0px;width:48px;</xsl:attribute>
          <xsl:when test="round($theRating) = 3 and round($theRating) &lt;= $theRating">
            <xsl:attribute name="style">background-image:url(/_layouts/images/Ratings.png);cursor:default;height:16px;margin:0px;background-repeat:no-repeat;background-position:-320px 0px;width:48px;</xsl:attribute>
          <xsl:when test="round($theRating) = 4 and round($theRating) &gt; $theRating">
            <xsl:attribute name="style">background-image:url(/_layouts/images/Ratings.png);cursor:default;height:16px;margin:0px;background-repeat:no-repeat;background-position:-320px 0px;width:62px;</xsl:attribute>
          <xsl:when test="round($theRating) = 4 and round($theRating) &lt;= $theRating">
            <xsl:attribute name="style">background-image:url(/_layouts/images/Ratings.png);cursor:default;height:16px;margin:0px;background-repeat:no-repeat;background-position:-304px 0px;width:64px;</xsl:attribute>
          <xsl:when test="round($theRating) = 5 and round($theRating) &gt; $theRating">
            <xsl:attribute name="style">background-image:url(/_layouts/images/Ratings.png);cursor:default;height:16px;margin:0px;background-repeat:no-repeat;background-position:-304px 0px;width:80px;</xsl:attribute>
          <xsl:when test="round($theRating) = 5">
            <xsl:attribute name="style">background-image:url(/_layouts/images/Ratings.png);cursor:default;height:16px;margin:0px;background-repeat:no-repeat;background-position:-160px 0px;width:80px;</xsl:attribute>

Click 'Ok' and save the page.

Search Results

You are ready to search for the results now ! My search page something like this 

So this brings to end of this post.

Thank you.. Have a nice day !
Happy Sharepointing !

Wednesday, 21 March 2012

Encode and Decode Refiner value from the Query URL

I hope you liked my previous post on "Adding Filter in the Refinement Panel of the Search Page". I was exploring more about how the Refinement works and I found out then whenever we hover over each filter on the refiner it shows the url value to be encoded.

Something like this,

if we decode the above url, we will get something like this

k=* specifies that i have performed the Keyword search for "*", i.e wildcard search
r=dttsource="AQpVUzpEU3RyZWV0CWR0dHNvdXJjZQEBIgEi" specifies that the list of fiters we have applied

Here i cannot know which filter I actually applied. Also it was difficult to understand how the refinement panel constructs the query string by combination of the multiple filters.
But it's very important for me to know which filter I applied, So i developed a small utility which will encode as well as decode the refiner value.

Decode Refiner Value from Query URL

Encode the Refiner Value from the filter name and column value

You can download both the utility from here

Note: For some OS/Browsers you might have to rename the files to .exe extension

I hope this post and utility was useful to you.

Thank you. Happy Sharepointing !