This is part three in a series on making an awesome search experience in Sitecore. The previous parts were on:

This means that we now have the basic data in Sitecore, and we have defined an index, that contains all the basic fields from Sitecore. Now it is time to index some of the special fields that could be used in the searching and displaying of results. The fields I’m going to index are some that I thing almost every time should be in the index. These are item url and image url. The two aren’t specific fields on an item, but are normally gotten by calling the LinkManager and the MediaManager. The problem is that these two functions takes the Sitecore Item, and when we are working on a search result, we don’t have the Sitecore Item. Instead, you have to make another call to Sitecore to get the actual item and then generate the urls. Having the url in the index will speed up performance greatly.

In order to index a custom field like the url, you need to make a class that inherits from IComputedIndexField (Sitecore.ContentSearch.ComputedFields.IComputedIndexField). For the Url to the item, it is done like this:

public class UrlComputedField : IComputedIndexField
{
    public object ComputeFieldValue(IIndexable indexable)
    {
        Item item = indexable as SitecoreIndexableItem;
        if (item == null)
            return null;
        // setting the context to website(sorry for hardcoding), to enable proper links
        using (new SiteContextSwitcher(Sitecore.Sites.SiteContext.GetSite("website")))
        {
            return LinkManager.GetItemUrl(item);
        }
        return null;
    }

    public string FieldName { get; set; }
    public string ReturnType { get; set; }
}

In the code above, the important method is the ComputedFieldValue. In this method, you have to put your code, and return the value you want to store in the index. In this example, we are generating the link to the item. It’s important to have the proper context, when generating the link, so using a SiteContextSwitcher will help you. I’ve hardcoded it to website in the above example, but this could be made more dynamic if needed.

With the field created in code, all we have to do is to register it in our search index, and add it to our search result item. Adding it to the search index will be done like this:

<fieldMap type="Sitecore.ContentSearch.FieldMap, Sitecore.ContentSearch">
  <fieldNames hint="raw:AddFieldByFieldName">
    ...
  </fieldNames>
</fieldMap>
<fields hint="raw:AddComputedIndexField">
  <field fieldName="url">MovieShop.BusinessLayer.Search.ComputedFields.UrlComputedField,MovieShop.BusinessLayer</field>
</fields>

In the definition, the field is made available with the name url, so in my MovieSearchResultItem, we simply add it as a property as all other fields:

[IndexField("url")]
public string Url { get; set; }

Just to show how easily it is to use, the following example is a sublayout that utilizes a list of the type MovieSearchResultItem, to display the movie’s title and a link to the actual item:

<asp:listview ID="lvMovies" runat="server" ItemType="MovieShop.BusinessLayer.Search.MovieSearchResultItem">
    <LayoutTemplate>
        <ul><asp:placeholder ID="itemPlaceholder" runat="server"/></ul>
    </LayoutTemplate>
    <ItemTemplate>
        <li>
            <div><a href="<%# Item.Url %>"><%# Item.OriginalTitle %></a></div>
        </li>
    </ItemTemplate>
</asp:listview>

That’s it, custom field for the search index. In addition to the url field, I’ve also created computed fields for:

Check the code out at the repository at Github

Existing code in Sitecore

I’ve been looking a lot at the existing code in Sitecore, to see how they have managed to index many of their fields. During this research I noticed that they already have an UrlLink (Sitecore.ContentSearch.ComputedFields.UrlLink) computed field. Unfortunately its LinkManager is hardcoded to resolve the links in a particular way; LanguageEmbedding=true, and ShortenUrls=true, and site=website. This is almost the same as the class I’ve implemented for the url field. It would be awesome for future versions of Sitecore, that the computed fields could be reused in our code. This could be by adding parameters to the index definition, like the LinkManager’s properties, or what field it should use when indexing.