Wednesday 27 January 2016

Sitecore 8.1 - Creating custom search index

Sitecore provides availability to configure and use custom search indexes. Starting from version 8.1 they are slightly different in configuration. In this article I will provide you with some advices to create your own Sitecore search index.

Differences from Sitecore 8.0

Let's take a quick look at the differences from version 8.0. When you open Sitecore.ContentSearch.Lucene.DefaultIndexConfiguration.config or Sitecore.ContentSearch.Solr.DefaultIndexConfiguration.config, you can see that sections where we define included and excluded templates, fields etc. are now wrapped with documentOptions tag:

<documentOptions type="Sitecore.ContentSearch.LuceneProvider.LuceneDocumentBuilderOptions, Sitecore.ContentSearch.LuceneProvider">
Also, names of the methods that includes/excludes specified elements now are different, for example,

<exclude hint="list:ExcludeTemplate">

is now replaced with

<exclude hint="list:AddExcludedTemplate">

That are the things I've conquered while upgrading from older Sitecore versions. Here's the list of changed names:

8.0 and before 8.1 and after
IncludeTemplate AddIncludedTemplate
ExcludeTemplate AddExcludedTemplate
IncludeField AddIncludedField
ExcludeField AddExcludedField
RemoveSpecialFields AddExcludedSpecialField

Creating custom search index

To define our own custom Sitecore custom index we will have to create config patch.

Here is version for Lucene

Here is version for Solr


Let's take a closer look now.

Extending default index configurations

Sitecore comes with default index configurations we can use to build our own index. There are versions for Lucene and Solr as well. To use it we are declaring ref attribute on <configuration> element:

<configuration ref="contentSearch/indexConfigurations/defaultLuceneIndexConfiguration">

<configuration ref="contentSearch/indexConfigurations/defaultSolrIndexConfiguration">

Indexing fields

With this setting:
<indexAllFields>true</indexAllFields> 
we declare that all fields will be indexed. This is by the way default setting in default Lucene index configuration.

We can set it to index only specific fields - indexAllFields should be set to false
<indexAllFields>false</indexAllFields> 
And then we should set our fields explicitly
<include hint="list:AddIncludedField">
  <Title>{96970EAB-F8C6-4DE2-A124-CDAC2DFD0C90}</Title> <!-- Title -->
  <Content>{EC539DFA-07C1-49A4-A094-87EACF5ED9BB}</Content> <!-- Content -->
</include>

Our index will also contain computed fields that come from default lucene index configuration. If we don't want them, then we should base our index on edited lucene index.

Including templates

The most important setting is where we define included templates. Only these templates will be indexed:
<include hint="list:AddIncludedTemplate">
    <Article>{C2198DA4-C89F-45D9-AF1A-E24C97F83398}</Article>
    <News>{24EBFFC0-27F0-4F18-A425-74D62F21609E}</News>
    <About>{804B99A2-B18E-4B86-A862-4D0270D4DEAB}</About>
</include>

I have included three example templates, they are declared with:
<templateName>Template ID</templateName>

It is also important to set up root path for the crawler:
<crawler type="Sitecore.ContentSearch.SitecoreItemCrawler, Sitecore.ContentSearch">
  <Database>web</Database>
  <Root>/sitecore/content/home</Root>
</crawler>

As we have complete index configuration lets save it in /App_Config/Include/OUR_CUSTOM_CONFIGS_FOLDER folder with file name format Sitecore.ContentSearch.Lucene.Index.OUR_INDEX_NAME.config. After that let's rebuild our new index.

Previewing indexes

After our index is built we can preview it. For Lucene indexes we can preview it with external tool named Luke (https://code.google.com/archive/p/luke/). It opens folder with index, usually located at Data/indexes folder:

Luke

For Solr indexes we basically open Solr Admin panel, by default set up on port 8983. We can access it by going to url http://localhost:8983/solr/

Solr admin panel


Querying index

As we have index built, we can run queries to get desired elements from index. Sitecore provides ContentSearch library and it is the proper way of searching index in Sitecore. It's completely independent from the implementation so switching index provider won't require code changes (in most cases of course ;)).

Here's a sample code that reads our custom index and searches for specified phrase:

var index = ContentSearchManager.GetIndex("SitecoreExperiments_index");
string phrase = "search phrase";
 
using (var context = index.CreateSearchContext())
{
    var searchQuery = context.GetQueryable<SearchResultItem>()
        .Where(x => x.Language.Equals(Sitecore.Context.Language.Name))
        .Where(x => x.Content.Contains(phrase));
 
    var resultItems = searchQuery.ToList();
    var totalCount = searchQuery.Count();
}

Sample project that provides custom search index and search service is available on my Helix project at GitHub - https://github.com/ReoKzK/SitecoreCoffee/tree/master/src/Foundation/Search/code