Search without special characters. Persister /Suggestion Persister/Facet

  Ticket 88715: [Kavo] 3.15. SEARCH – PUNCTUATION MARKS

Ticket 96724: [Kavo] 3.16 SEARCH – OEM# AND COMPETITOR# FIELDS

bachofn projects.


when the product index run 

it will Hit ExtractKeyword method on LucenIndexManager

public class ExtendedLuceneIndexManager : LuceneIndexManager
    {
         
 
        protected override IDictionary<stringstring> ExtractKeywords(IndexEntry entry)
        {
            var keywords = new Dictionary<stringstring>();

            foreach (var language in languageList)
            {
                var sb = new StringBuilder();
                foreach (var field in indexInfo.KeywordFields) <----from Admin section
                {
                    var persister = IndexFieldPersisterFactory.Current.GetPersister(field.Type);
                    if (!persister.IsSearchable)
                        throw new SanaBusinessException(String.Format("Field '{0}' cannot be a keyword field because the persistor does not allow this field to be searchable.", field.Name));
                    var value = persister.ExtractKeywords(entry.Entity, field, language);
                    sb.Append(value);
                    sb.Append(' ');
                }
                keywords.Add(language, sb.ToString());
            }

            return keywords;
        }
    }

to run it correctly you need to set Keyword fields. 



KeyWord .

can find all from Framework initializer

field No --> IdPersister / ExtendedIdPersister

Title --> TitlePersister

Description -->  ExtendedDescriptionPersister

etc ....

FrameworkInitializer

// Custom product persisters
            factory.Register(ProductIndexFieldTypes.Id, new ExtendedIdPersister());
            factory.Register(ProductIndexFieldTypes.Title, new ExtendedTitlePersister());
            factory.Register(ProductIndexFieldTypes.Price, new PricePersister());
            factory.Register(ProductIndexFieldTypes.VariantTitle, new VariantTitlePersister());
            factory.Register(ProductIndexFieldTypes.ProductCategory, new CategoryPersister());
            factory.Register(ProductIndexFieldTypes.VariantComponent, new VariantComponentPersister());
            factory.Register(ProductIndexFieldTypes.Description, new ExtendedDescriptionPersister());
            factory.Register(ProductIndexFieldTypes.OrderableProductGrossWeight, new OrderableProductGrossWeightPersister());
            factory.Register(ProductIndexFieldTypes.BarCode, new BarCodePersister());
            factory.Register(ProductIndexFieldTypes.Suggestion, new SuggestionPersister());


customization  for the issue, and run the Product index

public class ExtendedIdPersister : IdPersister
    {
        public override string ExtractKeywords(IEntity entity, IndexFieldInfo field, string language)
        { 
 
            //Ticket 88715: [Kavo] 3.15. SEARCH – PUNCTUATION MARKS.
 
            var keywords = base.ExtractKeywords(entity, field, language);
            //To accomodate the keworks without some character set
            var removableSeparators = new string[] { " "",""-""/" };
 
            var config = ConfigurationManager.AppSettings["RemovableSeparatorsForIndexFieldDescription"];
            if (!config.IsEmptyString())
                removableSeparators = config.Split(";").ToArray();
 
            var newKeywords = keywords;
 
            if (!keywords.IsEmptyString())
            {
                foreach (var separator in removableSeparators)
                {
                    if (newKeywords.Contains(separator))
                    {
                        newKeywords = newKeywords.Replace(separator, "");
                    }
                }
                keywords = keywords + " " + newKeywords;
            }
            return keywords;
        }
    }

public class ExtendedIdPersister : IdPersister
    {
        public override string ExtractKeywords(IEntity entityIndexFieldInfo fieldstring language)
        { 
            //Ticket 88715: [Kavo] 3.15. SEARCH – PUNCTUATION MARKS.                        
            var keywords = base.ExtractKeywords(entityfieldlanguage);
            var keywordWithooutSpecialCaracters = ExtendedProductSearchManager.ExtractKeywordwithSpecialCaracters(keywords);
            keywords += " " + keywordWithooutSpecialCaracters;
            return keywords;
        }
    }

public class ExtendedProductSearchManager : ProductSearchManager<ExtendedProductSearchIndexProvider>
    {
        /// <summary>
        /// This method will extract kewords
        /// </summary>
        /// <param name="keywords"></param>
        /// <returns></returns>
        public static string ExtractKeywordwithSpecialCaracters(string keywords)
        {
            //To accomodate the kewords without some character set
            var removableSeparators = new string[] { "-" };
 
            var config = ConfigurationManager.AppSettings["RemovableSeparatorsForIndexFieldDescription"];
            if (!config.IsEmptyString())
                removableSeparators = config.Split(";").ToArray();
 
            var newKeywords = keywords;
 
            if (!keywords.IsEmptyString())
            {
                foreach (var separator in removableSeparators)
                {
                    if (newKeywords.Contains(separator))
                    {
                        newKeywords = newKeywords.Replace(separator"");
                    }
                }                
            }
            return newKeywords;
        }
    }



Quick search on basket page use : SuggestionPersister.

public class ExtendedSuggestionPersister : SuggestionPersister
    {
        /// Ticket 88715: [Kavo] 3.15. SEARCH – PUNCTUATION MARKS.
        /// <summary>
        /// Extracts the keywords from the field for the specified language.
        /// </summary>
        /// <param name="entity">The entity.</param>
        /// <param name="field">The field.</param>
        /// <param name="language">The language.</param>
        /// <returns>Extracted keywords.</returns>
        public override string ExtractKeywords(IEntity entity, IndexFieldInfo field, string language)
        {
            var keywords = base.ExtractKeywords(entity, field, language);           
            keywords = ExtendedProductSearchManager.ExtractKeywordwithSpecialCaracters(keywords);            
            return keywords;
        }       
    }


This method helps : When user add Keyword Fields

public class ExtendedLuceneIndexManager  : LuceneIndexManager
    {
        protected override IDictionary<stringstring> ExtractKeywords(IndexEntry entry)
        {
            var keywords = new Dictionary<stringstring>();

            foreach (var language in languageList)
            {
                var sb = new StringBuilder();
                foreach (var field in indexInfo.KeywordFields)
                {
                    var persister = IndexFieldPersisterFactory.Current.GetPersister(field.Type);
                    if (!persister.IsSearchable)
                        throw new SanaBusinessException(String.Format("Field '{0}' cannot be a keyword field because the persistor does not allow this field to be searchable.", field.Name));
                    var value = persister.ExtractKeywords(entry.Entity, field, language);
                    sb.Append(value);
                    sb.Append(' ');
                }
                keywords.Add(language, sb.ToString());
            }

            return keywords;
        }        
        
    }

 it will call all the Persisters one by one .

This method helps : When user add FilterFields.

public class ExtendedLuceneIndexManager  : LuceneIndexManager    

protected virtual void AddFilterFields(Document doc, IndexEntry entry)
        {
            foreach (var field in indexInfo.FilterFields)
            {
                var persister = IndexFieldPersisterFactory.Current.GetPersister(field.Type);
                var index = persister.IsSortable && !persister.IsFilterable && !persister.IsSearchable ? Field.Index.NOT_ANALYZED : Field.Index.ANALYZED;
                var store = persister.IsRetrievable || persister.IsSortable ? Field.Store.YES : Field.Store.NO;
                var pairList = persister.GetValuesToIndex(entry.Entity, field).ToList();
                foreach (var pair in pairList)
                {
                    var strValue = persister.GetStringValue(pair.Value);
                    doc.Add(new Field(pair.Name, strValue, store, index));
                }
            }
        }



If string contains special caracter and you want to index those separately 

eg : Name1;Name3;name3; name4 

public class ExtendedStringFieldPersister : StringFieldPersister
    {
        protected override object GetPropertyValue(IEntity entitystring propertyName)
        {
            var pi = entity.GetType().GetProperty(propertyName);
            if (pi != null)
                return pi.GetValue(entitynull);
            
            // Ticket 100006: [Topmedia] 3.1. Search – Product Finder 
            // When split text by Product attribute split key.
            var value = entity.Fields.GetValue(propertyName).SafeToString();
            if (entity is Product && value.iContains(Constants.ProductAttributeSplitKey))
            {
                var val =  value.Split(Constants.ProductAttributeSplitKey).Aggregate((xy=> string.Join(Environment.NewLine, xy));
                return val;
            }
            return value;
        }
    }


public static class Constants

    {
        /// Ticket 100006: [Topmedia] 3.1. Search – Product Finder
        /// <summary>
        /// Product finder settings menu
        /// </summary>          
        public const string ProductAttributeSplitKey = ";";
    }


create new Persister 

/// Ticket 100006: [Topmedia] 3.1. Search – Product Finder
    /// <summary>
    /// Product Type Persister
    /// </summary>
    public class ProductTypePersister : StringFieldPersisterICustomIndexFieldPersister
    {
        /// <summary>
        /// Gets a value indicating whether the field can be searchable by keywords.
        /// </summary>
        /// <value>
        /// If not overridden in a derived class, returns <c>true</c>.
        /// </value>
        public override bool IsSearchable
        {
            get { return true; }
        }
 
        /// <summary>
        /// Gets a value indicating whether the field can be filterable.
        /// </summary>
        /// <value>
        /// If not overridden in a derived class, returns <c>false</c>.
        /// </value>
        public override bool IsFilterable
        {
            get { return true; }
        }
 
        /// <summary>
        /// Gets a value indicating whether the field can be sortable.
        /// </summary>
        /// <value>
        /// If not overridden in a derived class, returns <c>false</c>.
        /// </value>
        public override bool IsSortable
        {
            get { return false; }
        }
 
        /// <summary>
        /// Gets a value indicating whether the field should be retrievable from the index.
        /// </summary>
        /// <value>
        /// If not overridden in a derived class, returns <c>true</c>.
        /// </value>
        public override bool IsRetrievable
        {
            get { return true; }
        }
 
        /// Ticket 100006: [Topmedia] 3.1. Search – Product Finder
        public override IEnumerable<NameValuePairGetValuesToIndex(IEntity entityIndexFieldInfo field)
        {
            var productTypeCode = ((Product)entity).ProductTypeCode;
            var values = productTypeCode != null ? productTypeCode : string.Empty;
            yield return new NameValuePair(Constants.ProductTypeCode, values);
 
        }
 
        /// Ticket 100006: [Topmedia] 3.1. Search – Product Finder
        public override string ExtractKeywords(IEntity entityIndexFieldInfo fieldstring language)
        {
            var productTypeCode = ((Product)entity).ProductTypeCode;
            var values = productTypeCode != null ? productTypeCode : string.Empty;
            return values;
        }
 
 
        public IList<IFieldGetAvailableFields(string fieldType)
        {
            return null;
        }
 
        public void SetupIndexingLoadOptions(IEntityListLoadOptions loadOptionsIndexFieldInfo fieldIIndexInfo indexInfo)
        {
 
        }


Kavo Project

OemReferace are string list eg : 1000,1001,200,2005, .. 

then save as new line  

oemReferenceNumbers.JoinWith(Environment.NewLine)

public class OemReferenceNumbersPersister : StringFieldPersisterICustomIndexFieldPersister
    {
       ...
 
        /// Ticket 96724: [Kavo] 3.16 SEARCH – OEM# AND COMPETITOR# FIELDS       
        public override IEnumerable<NameValuePairGetValuesToIndex(IEntity entityIndexFieldInfo field)
        {
            var oemReferenceNumbers = ((Product)entity).OemReferenceNumbers;
            var values = oemReferenceNumbers != null ? oemReferenceNumbers.JoinWith(Environment.NewLine) : string.Empty;
            yield return new NameValuePair(Constants.OemReferenceNumbers, values);
 
        }
 
        /// Ticket 96724: [Kavo] 3.16 SEARCH – OEM# AND COMPETITOR# FIELDS
        public override string ExtractKeywords(IEntity entityIndexFieldInfo fieldstring language)
        {  
            var oemReferenceNumbers = ((Product)entity).OemReferenceNumbers;
            var values = oemReferenceNumbers != null ? oemReferenceNumbers.JoinWith(Environment.NewLine) : string.Empty;
            return values;
 
        } 
        ...


Compititor is a object 

get nessary field only and create a list and bind

var competitorsRefList = competitors?.Select(x => x.Reference).ToList(); 
var values = competitorsRefList != null ? competitorsRefList.JoinWith(Environment.NewLine)


public class CompetitorsPersister : StringFieldPersisterICustomIndexFieldPersister
    {        
       ......
        /// Ticket 96724: [Kavo] 3.16 SEARCH – OEM# AND COMPETITOR# FIELDS
        public override IEnumerable<NameValuePairGetValuesToIndex(IEntity entityIndexFieldInfo field)
        {
            var competitors = ((Product)entity).Competitors;
            var competitorsRefList = competitors?.Select(x => x.Reference).ToList();
 
            var values = competitorsRefList != null ? competitorsRefList.JoinWith(Environment.NewLine) : string.Empty;
            yield return new NameValuePair(Constants.Competitors, values);
        }
 
        /// Ticket 96724: [Kavo] 3.16 SEARCH – OEM# AND COMPETITOR# FIELDS
        public override string ExtractKeywords(IEntity entityIndexFieldInfo fieldstring language)
        {
            var competitors = ((Product)entity).Competitors;
            var competitorsRefList = competitors?.Select(x => x.Reference).ToList();
 
            var values = competitorsRefList != null ? competitorsRefList.JoinWith(Environment.NewLine) : string.Empty;
            return values;  
        } 
        .....
    }


register under custom product persisters

Frameworkinitializer.cs

// Ticket 96724: [Kavo] 3.16 SEARCH – OEM# AND COMPETITOR# FIELDS
 factory.Register(Constants.CompetitorsPersisterName, new CompetitorsPersister());
 factory.Register(Constants.OemReferenceNumbersPersisterName, new OemReferenceNumbersPersister());