You are here: Catalog System > Catalog Product Search

Catalog Product Search

Introduction

The Catalog Search API provides the functionality needed for finding products in the 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 SQL Server Full Text Search (FTS) feature and the other one is based on the Lucene .NET Engine (LS - Lucene Search). The FTS API should be familiar to our early adopters and somewhat familiar to users of previous generations of the EPiServer Commerce.

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

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 examples are Wikipedia, CNet, Monster, Apple, and FedEx. Lucene.NET was originally created using Java. However, the Lucene engine was later built from the ground up using .NET. Here are some of the capabilities of the search engine:

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 that are examples of how to use that API.

Advantages:

Drawbacks:

Primary Use: This API is used mostly on the frontend to provide more advanced functionality for the user.

Examples

Simple Catalog Entry Search

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. Please consult lucene documentation for more details on Query Parser Syntax.

Catalog Entry Fuzzy Search

In this example the results will be returned using fuzzy search, where approximate results will be returned. In this case it will be very similar to the previous example where we searched for "canon".

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();

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 the Web Controls like grid.

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:

Drawbacks:

Primary Use: This API is used mostly on the backend 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 out of the box functionality and will be beneficial for large scale 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 EPiServer Commerce.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 be perfrom the best with a smallest number of response groups returned.

Examples

Browsing Catalogs

The following is an example of browsing catalogs and categories.

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));
}
}

Searching by Keyword

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

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));
}

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).

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));
}

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.

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));

}
}

Searching on Metafield Values with Results Displaying via the API

Make sure all of your meta fields are searchable when you create them.
Here is a code sample:

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());
}

 


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