Wednesday, 27 January 2016

Sitecore 8.1 - Creating custom search index

Sitecore search index configuration slightly differs in version 8.1. In this article I will provide you with some advices to create your own Sitecore index.


Differences from Sitecore 8.0

The main difference lies in Sitecore.ContentSearch.Lucene.DefaultIndexConfiguration.config. Sections where we define included and excluded templates, fields etc. now is 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">


Creating custom search index

Let's define our own, working Sitecore search index. Here is the full code of the index config file. This is a Sitecore config patch.

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <contentSearch>
      <configuration type="Sitecore.ContentSearch.ContentSearchConfiguration, Sitecore.ContentSearch">
        <indexes hint="list:AddIndex">
          <index id="SitecoreExperiments_index" type="Sitecore.ContentSearch.LuceneProvider.LuceneIndex, Sitecore.ContentSearch.LuceneProvider">
            <param desc="name">$(id)</param>
            <param desc="folder">$(id)</param>
            
            <!-- This initializes index property store. Id has to be set to the index id -->
            <param desc="propertyStore" ref="contentSearch/indexConfigurations/databasePropertyStore" param1="$(id)" />
            
            <configuration ref="contentSearch/indexConfigurations/defaultLuceneIndexConfiguration">
 
              <documentOptions type="Sitecore.ContentSearch.LuceneProvider.LuceneDocumentBuilderOptions, Sitecore.ContentSearch.LuceneProvider">
 
                <indexAllFields>true</indexAllFields>
 
                <!-- Included templates -->
                <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>
 
              </documentOptions>
 
            </configuration>
            
            <strategies hint="list:AddStrategy">
              <!-- NOTE: order of these is controls the execution order -->
              <strategy ref="contentSearch/indexConfigurations/indexUpdateStrategies/onPublishEndAsync" />
            </strategies>
            <commitPolicyExecutor type="Sitecore.ContentSearch.CommitPolicyExecutor, Sitecore.ContentSearch">
              <policies hint="list:AddCommitPolicy">
                <policy type="Sitecore.ContentSearch.ModificationCountCommitPolicy, Sitecore.ContentSearch">
                  <Limit>300</Limit>
                </policy>
              </policies>
            </commitPolicyExecutor>
            
            <locations hint="list:AddCrawler">
              <crawler type="Sitecore.ContentSearch.SitecoreItemCrawler, Sitecore.ContentSearch">
                <Database>web</Database>
                <Root>/sitecore/content/home</Root>
              </crawler>
            </locations>
            
            <enableItemLanguageFallback>false</enableItemLanguageFallback>
            <enableFieldLanguageFallback>false</enableFieldLanguageFallback>
            
          </index>
        </indexes>
      </configuration>
    </contentSearch>
  </sitecore>
</configuration>

Our index will be based on default Lucene index configuration, so we will declare it by ref attribute on <configuration> element:

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

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.

We can preview our index with external tool named Luke (https://code.google.com/archive/p/luke/). It opens folder with index, usually located at Data/indexes folder:


As we have index built, we can run queries to get desired elements from index:
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();
}


Share it:

Radosław Kozłowski - Senior Sitecore Developer Radosław Kozłowski

Author & Editor

Senior Sitecore Developer and Team Leader with over 4 years experience

5 comments:

  1. wonderful information, I had come to know about your blog from my friend nandu , hyderabad,i have read atleast 7 posts of yours by now, and let me tell you, your website gives the best and the most interesting information. This is just the kind of information that i had been looking for, i'm already your rss reader now and i would regularly watch out for the new posts, once again hats off to you! Thanks a ton once again,
    Regards, sitecore training in hyderabad

    ReplyDelete
  2. Hi!

    Very interesting post! I have a question, I hope you are able to answer:

    How would I go about specifiying which fields to index, if I set the indexAllFields-tag to false?

    Thanks!

    ReplyDelete
    Replies
    1. Hi!
      I've just updated this post with some info that might be helpful for you.

      Cheers!

      Delete
  3. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. Thanks for very constructive and expressive criticism. This article was prepared strictly to show the differences between indexes configuration in versions 8.0 and 8.1. If you read it more carefully you will understand the difference. And also it is directed to more experienced Sitecore dev who knows where in which file put the index configuration and in which file put the sample c# code ;) But thanks again, I will try to make it more intern-friendly.

      Cheers!

      Delete