A good friend of mine Steve Peschka did a blog post during the SharePoint 2010 Beta which shows how to include a document’s rating within search results without writing any code. Well its been almost a year since that post and allot of things have changed. Since we RTM’ed SharePoint 2010 there are several key components to that blog that no longer work and this post is an attempt to update and hopefully add a little to the effort he started.
Turn on Ratings
To get started obviously we need Rating turned on in at least one list or library. For this example I will use a document library were I have uploaded a number of PowerPoint presentations and a few documents. To enable ratings I need to navigate to this document library and choosing “List settings” from the ribbon. From the Document Library settings page I choose “Rating settings” and I am presented with a super easy page to enable Ratings:
Once this setting is made a new column is added to my list and to the default view and at this point I can start rating content.
You may notice that once you start selecting a rating and then choose to refresh the page the rating might not “stick”. As you click on the stars and add a rating this is logged via an AJAX call into the social Database’s SocialRatings table. A timer job called the Social Data Maintenance Job which has the responsibility for walking through the SocialRatings table and calculating the average ratings and storing the results in the SocialRatings_Averages table. Its this table which is used to display the rating information which you see in the screenshot above and as a result any new rating will not be immediately visible on the web until the rating average has been calculated and move into this table.
Setting up Search
The next step is to create a Managed property in search that we can include in our search results. To have a Managed property you must first have a Crawled property so if you just turned on Rating for the first time and have yet to conduct a Full Crawl of search you need to do that now. If you are not sure navigate to your Crawled Properties by heading over to the search administration page within Central Administrator and choosing the Metadata properties link on the left navigation. Then choose the Crawled Properties link at the top and do a search for “rating”.
You should see two hits, one for ows_AverageRating and another for ows_RatingCount. If you don’t see these Crawled Properties kick off a Full Crawl in Search and wait for it to complete.
So lets add a Managed Property for each of the two Crawled Properties. First we will begin with the ows_AverageRating and create a Managed Property named ‘”Rating”. This value is of a decimal type and we need to choose the ows_AverageRating Crawled Property.
Next we will add a Managed Property named “RatingCount” which will be of type Integer and map it to the ows_RatingCount Crawled Property.
The last step here is to ensure both of our Crawled Properties are included in the index. We do this by selecting the “Include values for this property in the search index” checkbox on each Crawled Property.
After all of these changes have been made we need to do a Full Crawl of Search – this is super important; an incremental crawl will not suffice.
Customizing the XSLT
So while we are waiting on the Full Crawl to complete lets do some work to add the rating to the output of our search results. To do this we need to modify the XSLT of the Core Results WebPart on a search results page. Navigate to the search results page you plan on using and put the page into edit mode. Edit the properties of the Core Results WebPart by expanding the “Display Properties” section. We want to make 3 changes here:
- Uncheck the “Use Location Visualization” option
- Edit the Fetched Properties by adding the two new Managed properties to this list, for example: <Column Name=”Rating”/><Column Name=”RatingCount”/>
- Using the XSL Editor button we will add our new customized XSLT (source included below).
So the first two changes are relatively trivial to pull off and get right, but its this third change which is the money configuration change you need to get right so I will spend a bit more time talking about this one.
This first step to customizing the CoreResults WebPart’s XSL is to save the default XSLT. Please do this, I know backing up or saving data when you may never need it is not sexy but it only takes maybe one minute of time and if you put it in a safe spot you never need to do it again. Sure you could just add another CoreResults Webpart and pull the default XSLT from that but that will take more time.
With the default XSL saved off we will make a copy of this file as the start of our customized XSLT. Word of warning here, XSL is not the most strait forward language to learn as you are using XML syntax to manipulate data. It takes a bit of getting use to but its not too hard to figure out especially when you have a large XSLT here to play around with and look for examples. The XSL we are going to add in this example is in two separate chunks – the first is the template and the second is the callout to the template itself. If you are a developer you will liken this to a method definition and a call to the method where the method definition is the template.
We begin editing the XSLT by adding the callout to our template. Within the “Result” template is where we want to insert this first bit of customization. Specifically we want to place it just after line 407 which should be a closing choose tag, eg: </xsl:choose> but before the first of the two </div> tags.
<!--Start Rating--> <xsl:call-template name="FormatRating"> <xsl:with-param name="theRating" select="rating" /> <xsl:with-param name="theRatingCount" select="ratingcount" /> </xsl:call-template> <!--End Rating-->
So with the template callout in place its time to add our template. We want to add this to the bottom of the XSLT just above the last tag which will be the stylesheet tag.
<!--Start Rating--> <xsl:template name="FormatRating"> <xsl:param name="theRating" /> <xsl:param name="theRatingCount" /> <xsl:if test="$theRating > 0">
</div> </xsl:if> </xsl:template> <!–End Rating–>
Once both edits are in place you can save the XSL and place into the Core Results WebPart.
So what is this XSL actually doing? Well the template (or method if you so choose) is named FormatRating and it takes two parameters. The first is the rating and the second is the rating count both of which are pulled from the XML sent to us as part of the search results from a query. The FormatRating template uses these two values to add an <div> into the resulting HTML. The background of the div is an image named Ratings.png which is part of the SharePoint 2010 installation. This image is a sprite and contains a few images within a single image file so the file is only downloaded once from the server but visually appears as many different images.
Each star is 16×16 and I use CSS styling to index into the image and show from 1 to 5 stars as well as half stars were necessary. All position and widths are divisible by 16 as I move the mask around to show different parts of the image based on the number of stars each item has been rated. I use the title property on the div to display the number of stars as well as the number of ratings.
As you can see from the screenshot below we now have rating data returned within the search results and we did all of this without writing any code (this is true if you don’t consider XSL code, otherwise I just lied to you).