Loading...
ARCHIVED This content is retired and no longer maintained. See the latest version here.

Recommended reading 

The Catalog Search API provides the functionality needed for finding products in EPiServer Commerce using a variety of methods.

There are two distinct APIs that provide search functionality and each one of them offers unique capabilities. One is based on the Lucene .NET Engine (LS - Lucene Search), and the other is based on the SQL Server Full Text Search (FTS) feature.

The Catalog Search API is used to accomplish the following functionality:

  • Browsing catalogs and categories
  • Performing site-wide searches by keywords
  • Guided search
  • Browsing by brand, price and any other meta fields

Lucene search

Lucene.NET is a powerful search engine that is used by a number of popular sites with large amounts of data to index. Some of the capabilities of this search engine are:

  • Full text search indexing
  • Ranked search results
  • Different query types available, for instance phrase queries
  • Searching by field Numeric value range searches
  • Date range searches
  • "Did you mean" functionality to provide user with corrected search terms

Lucene.NET is a framework library, not a stand-alone application. It is integrated into EPiServer Commerce, which provides an API wrapper around the Lucene.NET search engine and several controls exemplifying how to use the API.

Advantages:

  • Very fast search with capability to do counts and filters
  • Allows controlling indexing and searching process
  • Open Source architecture

Disadvantages:

  • Have to manually update indexes
  • Have to come up with workarounds for multi server environments
  • Uses it's own query language

Primary use: This API is used mostly on the front-end to provide more advanced functionality for website visitors.

Implementation examples

In the following we will provide some examples of how to implement search features with Lucene search.

Example: Simple catalog entry search

C#
CatalogEntrySearchCriteria criteria = new CatalogEntrySearchCriteria();
            criteria.SearchPhrase = "canon";
            SearchManager manager = new SearchManager(AppContext.Current.ApplicationName);
            SearchResults results = manager.Search(criteria);

The SearchPhrase property can contain full Lucene Syntax like: title:"The Right Way" AND text:go. Refer to the Lucene documentation for more details on Query Parser Syntax.

Example: Catalog entry fuzzy search

In this example the results will be returned using fuzzy search, where approximate results will be returned.

C#
CatalogEntrySearchCriteria criteria = new CatalogEntrySearchCriteria();
            criteria.SearchPhrase = "fanon";
            SearchManager manager = new SearchManager(AppContext.Current.ApplicationName);
            SearchResults results = manager.Search(criteria);
            if (results.TotalCount == 0)
            {
            criteria.IsFuzzySearch = true;
            criteria.FuzzyMinSimilarity = 0.7f;
            results = manager.Search(criteria);
            }
            Console.Write("Total Results: " + results.TotalCount.ToString();

Example: Catalog entry search with paging

This example shows how to return real Catalog Entries from the search API which can be used to bind directly to Web Controls like grid.

C#
ICatalogSystem system = CatalogContext.Current;
            // Get catalog lists
            CatalogDto catalogs = system.GetCatalogDto();

            // Create Entry Criteria
            CatalogEntrySearchCriteria criteria = new CatalogEntrySearchCriteria();
            // Bind default catalogs if none found
            if (criteria.CatalogNames.Count == 0)
            {
            if (catalogs.Catalog.Count > 0)
            {
            foreach (CatalogDto.CatalogRow row in catalogs.Catalog)
            {
            if (row.IsActive &&
            row.StartDate <= FrameworkContext.Current.CurrentDateTime &&
            row.EndDate >= FrameworkContext.Current.CurrentDateTime)
            {
            criteria.CatalogNames.Add(row.Name);
            }
            }
            }
            }

            // Define phrase we want to search
            criteria.SearchPhrase = "canon";

            // Create a manager
            SearchManager manager = new SearchManager(AppContext.Current.ApplicationName);

            SearchResults results = null;

            // Define sort parameter
            criteria.Sort = new SearchSort("DisplayName");


            // Perform search
            results = manager.Search(criteria);


            Assert.IsTrue(results.TotalCount > 0, "No hits were found in Lucene index.");


            // Get IDs we need
            int[] resultIndexes = results.GetIntResults(0, 10 + 5); // we add padding here to accomodate entries that might have been deleted since last indexing
            // Retrieve actual entry objects, with no caching
            Entries entries = CatalogContext.Current.GetCatalogEntries(resultIndexes, false, new TimeSpan(), new CatalogEntryResponseGroup(CatalogEntryResponseGroup.ResponseGroup.CatalogEntryFull));
            entries.TotalResults = results.TotalCount;
            Assert.IsTrue(entries.TotalResults > 0, "No entries were returned from the database.");

Full-text search

Advantages:

  • Provides up to date data queries that are directly integrated with SQL Server
  • Data is automatically repopulated and managed by SQL Server
  • There are native TSQL commands to manipulate the FTS catalogs

Disadvantages:

  • Slow and does not provide ways to optimize indexing
  • Does not include functionality like fuzzy or proximity search which makes it hard to use such functionality

Primary use: This API is used mostly on the back-end where performance is not that critical.

Optimization

Catalog Search uses SQL Server Full Text Search capability out-of-the-box to optimize search requests. Other search products can be used to compliment this default functionality, and will be beneficial for large scale e-commerce sites.

Caching

The search API has a very flexible caching mechanism which allows developer to control how caching is handled by the search. A developer can specify whether or not results should be cached and the specific amount of time they should be cached. The properties are CacheResults (bool) and CacheTimeout (TimeSpan). You would generally want to cache simple search requests like browsing major categories. Since these requests will be the same for a large audience, it will benefit the performance of the site. On the other hand, you might not want to cache specific keyword searches, since those will be unique to a user and have a smaller chance of benefiting through caching.

You can change caching on the public site by going to the ecf.catalog.config file in your \PublicLayer\SDKs\B2CSampleSite\Configs folder and changing appropriate values in the <Cache/> element.

Response groups

Response groups are another way to make sure the site is performing to the maximum. When searching for entries/products in EPiServer Commerce, you can specify the response groups that should be returned. The search will perform the best with a smallest number of response groups returned.

Implementation examples

In the following we will provide some examples of how to implement search features with Full Text search.

Example: Browsing catalogs

The following is an example of browsing catalogs and categories.

C#
ICatalogSystem system = CatalogContext.Current;
            // Get catalog lists
            CatalogDto catalogs = system.GetCatalogDto();
            foreach (CatalogDto.CatalogRow catalog in catalogs.Catalog)
            {
            string catalogName = catalog.Name;
            // Get Catalog Nodes
            CatalogNodeDto nodes = system.GetCatalogNodesDto(catalogName);
            foreach (CatalogNodeDto.CatalogNodeRow node in nodes.CatalogNode)
            {
            CatalogSearchParameters pars = new CatalogSearchParameters();
            CatalogSearchOptions options = new CatalogSearchOptions();
            options.CacheResults = true;
            pars.CatalogNames.Add(catalogName);
            pars.CatalogNodes.Add(node.Code);
            Entries entries = CatalogContext.Current.FindItems(pars,
            options,
            new CatalogEntryResponseGroup(CatalogEntryResponseGroup.ResponseGroup.CatalogEntryFull));
            }
            }

Example: Searching by keyword

The following example shows how to search catalogs using the specified keyword.

C#
ICatalogSystem system = CatalogContext.Current;// Get catalog lists
            CatalogDto catalogs = system.GetCatalogDto();


            foreach (CatalogDto.CatalogRow catalog in catalogs.Catalog)
            {
            string catalogName = catalog.Name;

            // Get Catalog Nodes
            CatalogSearchParameters pars = new CatalogSearchParameters();
            CatalogSearchOptions options = new CatalogSearchOptions();

            pars.FreeTextSearchPhrase = "policy";
            pars.CatalogNames.Add(catalogName);

            Entries entries = CatalogContext.Current.FindItems(pars, options, new CatalogEntryResponseGroup(CatalogEntryResponseGroup.ResponseGroup.CatalogEntryFull));
            }

Example: Advanced keyword search

This example shows how to search catalogs using more advanced queries. You can specify additional parameters like "near". The tables are searched using the Full Text Search "ContainsTable" function. For more information refer to CONTAINSTABLE (Transact-SQL).

C#
ICatalogSystem system = CatalogContext.Current;
            // Get catalog lists
            CatalogDto catalogs = system.GetCatalogDto();

            foreach (CatalogDto.CatalogRow catalog in catalogs.Catalog)
            {
            string catalogName = catalog.Name;


            // Get Catalog Nodes
            CatalogSearchParameters pars = new CatalogSearchParameters();
            CatalogSearchOptions options = new CatalogSearchOptions();
            pars.AdvancedFreeTextSearchPhrase = "(\"sweet and savory\" NEAR sauces) OR (\"sweet and savory\" NEAR candies)";
            pars.CatalogNames.Add(catalogName);

            Entries entries = CatalogContext.Current.FindItems(pars, options, new CatalogEntryResponseGroup(CatalogEntryResponseGroup.ResponseGroup.CatalogEntryFull));
            }

Example: Join table search

The Catalog API allows joining additional tables, queries or views to the search query. This allows further customizations to the search without any modifications to the core framework. For example if you want to sort by meta fields you can join the specific meta table and you will be able to specify fields from meta table in your order by statements. The example below orders entries by DisplayName.

C#
ICatalogSystem system = CatalogContext.Current;

            // Get catalog lists
            CatalogDto catalogs = system.GetCatalogDto();

            foreach (CatalogDto.CatalogRow catalog in catalogs.Catalog)
            {
            string catalogName = catalog.Name;

            // Get Catalog Nodes
            CatalogNodeDto nodes = system.GetCatalogNodesDto(catalogName);
            foreach (CatalogNodeDto.CatalogNodeRow node in nodes.CatalogNode)
            {
            CatalogSearchParameters pars = new CatalogSearchParameters();
            CatalogSearchOptions options = new CatalogSearchOptions();
            options.CacheResults = true;

            pars.CatalogNames.Add(catalogName);
            pars.CatalogNodes.Add(node.Code);
            pars.JoinType = "inner join";
            pars.Language = "en-us";
            pars.JoinSourceTable = "CatalogEntry";
            pars.JoinTargetQuery = "(select distinct ObjectId, DisplayName from CatalogEntryEx) CatalogEntryEx";
            pars.JoinSourceTableKey = "CatalogEntryId";
            pars.JoinTargetTableKey = "CatalogEntryEx.ObjectId";
            pars.OrderByClause = "CatalogEntryEx.DisplayName";

            Entries entries = CatalogContext.Current.FindItems(pars, options, new CatalogEntryResponseGroup(CatalogEntryResponseGroup.ResponseGroup.CatalogEntryFull));

            }
            }

Example: Searching on metafield values with results displayed via the API

C#
private void testCatalogEntiresSearch()
            {
            CatalogSearchParameters parameters = new CatalogSearchParameters();
            parameters.SqlMetaWhereClause = "Meta.DisplayName = 'Canon'";
            CatalogSearchOptions options = new CatalogSearchOptions();
            options.Classes.Add("Brands");
            options.RecordsToRetrieve = 20;
            Entries result = CatalogContext.Current.FindItems (parameters, options, new CatalogEntryResponseGroup());
            }
Make sure all of your meta fields are searchable when you create them.
Do you find this information helpful? Please log in to provide feedback.

Last updated: Oct 21, 2014

Recommended reading