Issue: User was getting unexpected search results for products, e.g. with a search key word ‘Sate’ he was getting same result as for ‘Site’. Although for most of the clients they will happy with these results but this particular client was unhappy with this result due to their business requirements. We do not have any word like ‘Sate’ in our Database or in Index file for Lucene. Clearly it was Fuzzy search that was causing this although in code we have set FuzzySearch = false;
Reason:
// Perform Lucene search
SearchResults results = searchFilterHelper.SearchEntries(criteria) as SearchResults;
In the Mediachase.Commerce.Website, Version=5.2.243.2, SearchFilterHelper’s SearchEntries() method, below:
public virtual ISearchResults SearchEntries(CatalogEntrySearchCriteria criteria) { try {
_Results = Manager.Search(criteria);
}
catch (SystemException)
{
if (HttpContext.Current.IsDebuggingEnabled)
throw;
}
// Perform fuzzy search if nothing has been found
if (_Results.TotalCount == 0) {
criteria.IsFuzzySearch = true;
criteria.FuzzyMinSimilarity = 0.7f;
_Results = Manager.Search(criteria);
}
return _Results;
}
As you can see there is an initial call to Manager.Search().
Before returning, the TotalCount property on the ISearchResults object returned is checked to see if there were no results.
If there are no results a fuzzy search is done.
That was causing the issue although iSFuzzySearch was false at the time of request.
Fix: A fix is present in Episerver Commerce R2 Sp2. There is an extra Function is available that can be used to stop FuzzySearch if no result is found with actual keyword.
public virtual ISearchResults SearchEntries(CatalogEntrySearchCriteria criteria, bool isFuzzySearch, float minSimilarity)
// Perform Lucene search
SearchResults results = searchFilterHelper.SearchEntries(criteria,false,0) as SearchResults;
Special thanks to Jeff from EpiServer’s Developer Support team to find out the reason and fix.
Example Code:
internal CatalogIndexSearchDataSource CreateDataSource(SearchFilterHelper filter, int pageNo, int pageSize, ref int totalRows, bool cacheResults, int cacheTime, string nodeString, string keywords, List<string> metaClasses)
{
var currentCulture = Thread.CurrentThread.CurrentUICulture;
Thread.CurrentThread.CurrentUICulture = new CultureInfo(SiteContext.Current.LanguageName);
var recordsToRetrieve = pageSize;
//cache timeout
TimeSpan cacheTimeout = new TimeSpan(0, (int)cacheTime, 0);
// Perform search
SearchSort sortObject = null;
// Put default sort order if none is set
if (sortObject == null)
sortObject = CatalogEntrySearchCriteria.DefaultSortOrder;
var criteria = filter.CreateSearchCriteria(keywords, sortObject);
//If meta classes are given to search.
if (metaClasses != null)
foreach (string metaClass in metaClasses)
criteria.SearchIndex.Add(metaClass);
//Add catalogs
foreach (var row in CatalogContext.Current.GetCatalogDto(SiteContext.Current.SiteId).Catalog)
{
if (row.IsActive && row.StartDate <= FrameworkContext.Current.CurrentDateTime && row.EndDate >= FrameworkContext.Current.CurrentDateTime)
criteria.CatalogNames.Add(row.Name);
}
//add catalog nodes
if (!string.IsNullOrEmpty(nodeString))
{
foreach (string outline in SearchFilterHelper.GetOutlinesForNode(nodeString))
{
criteria.Outlines.Add(outline);
}
}
CatalogIndexSearchDataSource dataSource = null;
// No need to perform search if no catalogs specified
if (criteria.CatalogNames.Count != 0)
{
Entries entries = new Entries();
// Perform Lucene search
SearchResults results = searchFilterHelper.SearchEntries(criteria,false,0) as SearchResults;
// Get IDs we need
int[] resultIndexes = results.GetIntResults(pageNumber , maxRows+5); // we add padding here to accomodate entries that might have been deleted since last indexing
if (resultIndexes.Length > 0)
{
int[] productResultIndexes = RefinementHelper.GetParentProducts(pageSize, pageNumber, resultIndexes, ref totalRows);
// Retrieve actual entry objects, with no caching
entries = CatalogContext.Current.GetCatalogEntries(productResultIndexes, false, new TimeSpan(), responseGroup);
// Add in attribute information
AddAttributes(entries, results);
// Insert to the cache collection
entries.TotalResults = totalRows;
CatalogCache.Insert(cacheKey, entries, cacheTimeout); dataSource = new CatalogIndexSearchDataSource { TotalResults = totalRows, CatalogEntries = entries };
}
Thread.CurrentThread.CurrentUICulture = currentCulture;
return dataSource;
}