You are here: Architecture > Searching and Indexing

Searching and Indexing


EPiServer Commerce includes an extensive system wide search engine. Any information can be made available to the search engine even if that information is not included as part of the EPiServer Commerce Database. The engine itself consists of two major parts: indexing & search. Indexing is responsible for adding data into the search engine and search is all about retrieving the data. More about these two components will be explained later.

The search engine itself is based on the provider model, meaning you can write your own providers to search servers if you want or need to. The process of writing a new provider will be explained in this section. EPiServer Commerce comes with couple providers out of the box (Lucene and SOLR Server) and more will be available as 3rd party add ons. Just ask our sales team and they will let you know what is currently available.

Also please note that some systems (Catalog & Order) offer additional search functionality that is not using search engine explained in this section. Please refer to a system documentation regarding that search functionality.


In order for the data to be available it will first need to be indexed. The indexing is done by the call to Mediachase.Search.SearchManager.BuildIndex(bool rebuild) method. This method is called by either clicking "Build" or "Rebuild" buttons in the Commerce Manager or through the quartz service that calls BuildIndex method on the predefined schedule.

The individual indexer implementations are defined in file. The default catalog indexer included (Mediachase.Search.Extensions.Indexers.CatalogIndexBuilder, Mediachase.Search.Extensions) with a package reads the catalog data and calls the SearchProvider.Index(string applicationName, string scope, ISearchDocument document) method. The method must be implemented by the provider that is currently configured (the provider is configured inside same Mediachase.Search.config file). The provider will be passed an ISearchDocument containing the properties that need to be indexed. You can either replace the indexer completely or extend the existing indexer by inheriting CatalogIndexBuilder class and overriding OnCatalogEntryIndex method. New indexers can also be added. By default indexer only populates fields that are marked searchable in the meta configuration as well as some of the system fields like (price, name, code and so on). Depending on the provider additional configuration changes need to be made for those fields to make it to the index.

Calling BuildIndex with rebuild = false will only add indexes that has changed since the last index was done. The system keeps track of when the last index was performed using the ".build" file. Location of the ".build" file is configured inside Mediachase.Search.config file for each indexer defined.

Build index command

1 SearchManager searchManager = new SearchManager(applicationName);
2 searchManager.BuildIndex(false);

Adding new field to the index.

The process of adding the new field can be different depending on the provider you use and where the data is coming from. Here we explain the steps to add field for the catalog index using Lucene and SOLR providers.

When using Lucene and you simply want to add meta field to be searchable, simply go to the meta field configuration in the commerce manager and mark it as searchable. The field will be automatically added to the index. When using SOLR you will need to do extra step and add that field into SOLR configuration file which is located APACHERROOT\solr\catalog\conf\catalog.schema.xml like this:

SOLR Schema

<field name="MyNewField" type="string" indexed="true" stored="true" multiValued="true" />


To add a field programatically (for the case when data comes from external data source or needs to be computed), you will need to create a new class that inherits existing CatalogIndexer:

Custom Index Class

01 public class MyCatalogIndexedr : Mediachase.Search.Extensions.Indexers.CatalogIndexBuilder
02 {
03 /// <summary>
04 /// Called when catalog entry is indexed. Override this method to add some extra fields.
05 /// </summary>
06 /// <param name="document">The document.</param>
07 /// <param name="entry">The entry.</param>
08 /// <param name="language"></param>
09 protected override void OnCatalogEntryIndex(ref SearchDocument document, CatalogEntryDto.CatalogEntryRow entry, string language)
10 {
11 // Example, add all apple products as featured
12 if(entry.Name.Contains("apple"))
13 document.Add(new SearchField("featured", true));
15 base.OnCatalogEntryIndex(ref document, entry, language);
16 }
17 }

Implementing new Search Indexer

Search Indexer is a component that is responsible for assembling data into documents that Search Provider can then index. It typically connects sub systems like Catalog, gets a list of changes and submits it to the search provider. By default EPiServer Commerce comes with just Catalog Search indexer. To implement a new indexer for example to be able to search for Orders, you will need to implement ISearchIndexBuilder interface which looks like this:

Simple catalog search

01 /// <summary>
02 /// Search Index Builder Interface.
03 /// </summary>
04 public interface ISearchIndexBuilder
05 {
06 /// <summary>
07 /// Builds the index.
08 /// </summary>
09 /// <param name="rebuild">if set to <c>true</c> the full rebuild will be done, if not. The last build date will be used.</param>
10 void BuildIndex(bool rebuild);
12 /// <summary>
13 /// Gets or sets the manager.
14 /// </summary>
15 /// <value>The manager.</value>
16 SearchManager Manager {get;set;}
18 /// <summary>
19 /// Gets or sets the build indexer.
20 /// </summary>
21 /// <value>The build indexer.</value>
22 IndexBuilder Indexer { get; set; }
23 }

It might be easier to reuse BaseIndexBuilder class instead since it contains helper methods, but it is not required.

Once your indexer is ready, simply add it to the Mediachase.Search.config and should be ready to use. Not that the indexer itself is provider independent and should work with any provider.


Search is done by calling ISearchResults Mediachase.Search.Search(ISearchCriteria criteria) method. The method call is handled by the configured search provider and returns the ISearchResults interface.

Simple catalog search

1 CatalogEntrySearchCriteria criteria = new CatalogEntrySearchCriteria();
2 criteria.SearchPhrase = "canon";
3 SearchManager manager = new SearchManager(AppContext.Current.ApplicationName);
4 SearchResults results = manager.Search(criteria);

The search phrase can contain complex search syntax that is specific to a provider used. The exact syntax for SOLR provider can be found here.


Search engine comes with support for custom filters with counters (ie price range, brands and so on). These filters are called facets and can be specified as part of the ISearchCriteria interface.

The front end includes controls that read special conig file to automatically populate the facet property of the ISearchCriteria interface. These filters are stored in Mediachase.Search.Filters.config. To add a new filter simply add new field into index and add a record to the config file. The filter will appear as soon as the data is available.

Creating new Search Provider

To implement a new search provider or to extend/replace existing one, you will need to create a new class that implements SearchProvider abstract class. That class contains one method that performs the search while the rest deal with indexing the data. It is typically much easier to take one of the existing implementations (SOLR or Lucene) as a starting point.

SearchProvider class

01 public abstract class SearchProvider : ProviderBase
02 {
03 /// <summary>
04 /// Gets the class type of the query builder. This class will be used to dynamically convert SearchCriteria to the query
05 /// that Search Provider can understand.
06 /// </summary>
07 /// <example>
08 /// // the following type will build query for the SOLR server
09 /// "Mediachase.Search.Providers.Solr.SolrSearchQueryBuilder, Mediachase.Search.SolrSearchProvider"
10 /// </example>
11 /// <value>The type of the query builder.</value>
12 public abstract string QueryBuilderType { get; }
14 /// <summary>
15 /// Searches the datasource using the specified criteria. Criteria is parsed by the query builder specified by <typeparamref name="QueryBuilderType"/>.
16 /// </summary>
17 /// <param name="applicationName">Name of the application.</param>
18 /// <param name="criteria">The criteria.</param>
19 /// <returns></returns>
20 public abstract ISearchResults Search(string applicationName, ISearchCriteria criteria);
22 /// <summary>
23 /// Adds the document to the index. Depending on the provider, the document will be commited only after commit is called.
24 /// </summary>
25 /// <param name="applicationName">Name of the application.</param>
26 /// <param name="scope">The scope.</param>
27 /// <param name="document">The document.</param>
28 public abstract void Index(string applicationName, string scope, ISearchDocument document);
30 /// <summary>
31 /// Removes the document by specifying scope (core in SOLR), key (a field that can be used to lookup for a document) and
32 /// value of the key.
33 /// </summary>
34 /// <param name="applicationName">Name of the application.</param>
35 /// <param name="scope">The scope.</param>
36 /// <param name="key">The key.</param>
37 /// <param name="value">The value.</param>
38 /// <returns></returns>
39 public abstract int Remove(string applicationName, string scope, string key, string value);
41 /// <summary>
42 /// Removes all documents in the specified scope.
43 /// </summary>
44 /// <param name="applicationName">Name of the application.</param>
45 /// <param name="scope">The scope.</param>
46 public abstract void RemoveAll(string applicationName, string scope);
48 /// <summary>
49 /// Closes the specified provider.
50 /// </summary>
51 /// <param name="applicationName">Name of the application.</param>
52 /// <param name="scope">The scope.</param>
53 public abstract void Close(string applicationName, string scope);
55 /// <summary>
56 /// Commits changes made to this instance.
57 /// </summary>
58 /// <param name="applicationName">Name of the application.</param>
59 public abstract void Commit(string applicationName);
60 }

The main classes in this SOLR implementation are called:


Last updated: 2011-05-17 | Copyright © EPiServer AB | Send feedback to us