Search Index with custom fields in sitefinity 4

Search Index with custom fields in sitefinity 4

Posted on November 14, 2011 0 Comments

The content you're reading is getting on in years
This post is on the older side and its content may be out of date.
Be sure to visit our blogs homepage for our latest news, updates and information.

This is going to be a HOW to configure  the search indexes in sitefinity to index and search on more than the default fields. 

1. You have to add the fields in sitefinity search index. The search system is based on the publishing system so the way to add additional fields is  like this :   


var ContentSearchPipesSettigns = PublishingSystemFactory.GetTemplatePipes("SearchItemTemplate").Where(ps => ps.PipeName == ContentInboundPipe.PipeName && ps.IsInbound).FirstOrDefault();
 
          if (!ContentSearchPipesSettigns.Mappings.Mappings.Any(mp => mp.DestinationPropertyName == "TestField"))
          {
              var mapping = PublishingSystemFactory.CreateMapping("TestField", TransparentTranslator.TranslatorName, false, "TestField");
 
              ContentSearchPipesSettigns.Mappings.Mappings.Add(mapping);
 
              PublishingSystemFactory.RegisterTemplatePipe("SearchItemTemplate", ContentSearchPipesSettigns, ps => ps.PipeName == ContentInboundPipe.PipeName && ps.IsInbound);
          }
 
 
          var searchPipesSettigns = PublishingSystemFactory.GetTemplatePipes("SearchItemTemplate").Where(ps => ps.PipeName == SearchIndexOutboundPipe.PipeName && !ps.IsInbound).FirstOrDefault();
 
          if (!searchPipesSettigns.Mappings.Mappings.Any(mp => mp.DestinationPropertyName == "TestField"))
          {
              var mappingTest = PublishingSystemFactory.CreateMapping("TestField", TransparentTranslator.TranslatorName, false, "TestField");
 
              searchPipesSettigns.Mappings.Mappings.Add(mappingTest);
 
              PublishingSystemFactory.RegisterTemplatePipe("SearchItemTemplate", searchPipesSettigns, ps => ps.PipeName == SearchIndexOutboundPipe.PipeName && !ps.IsInbound);
          }

First we add a  field named "TestField" in the inbound pipe and second  part add the field into the search index pipe.  This is changing the default search index template so all your search indexes should be recreated (deleted and created again) to apply this settings. 

2. Now you have the field in the search index. So now you have to replace the provider to be able to have control over the fields that are part of the search queries : 


var section = Config.Get<SearchConfig>();
           foreach (var provider in section.Providers.Values)
           {
               if (provider.Name == "LuceneSearchProvider")
               {
                   if (provider.ProviderType == typeof(LuceneSearchProvider))
                   {
                       provider.ProviderType = typeof(LucenseCustomSearchProvider);
                       ConfigManager.GetManager().SaveSection(section);
                       break;
                   }
               }
           }

3. You have to implement this Custom lucene  search provider  like this  : 


public class LucenseCustomSearchProvider : LuceneSearchProvider
    {
        public override IResultSet Find(string catalogueName, string query, int skip, int take, params string[] orderBy)
        {
            return new LuceneCustomResultSet(this, catalogueName, query, skip, take, orderBy);
        }
 
        public override IResultSet Find(string catalogueName, string query, params string[] orderBy)
        {
            return new LuceneCustomResultSet(this, catalogueName, query, orderBy);
        }
    }

4. And the last thing is to implement the custom search result set  : 

public class LuceneCustomResultSet : LuceneResultSet
{
 
     public LuceneCustomResultSet(LuceneSearchProvider provider, string catalogueName, string query, params string[] orderBy)
        : this(provider, catalogueName, query, 0, 0, orderBy)
    {
         
    }
 
     string catalogueName = String.Empty;
     public LuceneCustomResultSet(LuceneSearchProvider provider, string catalogueName, string query, int skip, int take, params string[] orderBy)
         : base(provider, catalogueName, query, 0, 0, orderBy)
     {
         this.catalogueName = catalogueName;
         this.query = query;
     }
 
    protected override void ExecuteQuery(bool tryToFix = true)
    {
        try
        {
            var path = ((LuceneSearchProvider)SearchManager.GetManager("").Provider).GetCataloguePath(catalogueName);
            if (System.IO.Directory.Exists(path))
            {
                var defautlOperator = QueryParser.AND_OPERATOR;
                var analyzer = this.GetAnalyzer();
 
                var parser = new MultiFieldQueryParser(new string[] { "Title", "Content", "TestField" }, analyzer);
                parser.SetDefaultOperator(defautlOperator);
 
                //query = QueryParser.Escape(query);
 
                if (searcher != null)
                    searcher.Close();
 
                searcher = new IndexSearcher(path);
                Query queryObj = searcher.Rewrite(parser.Parse(query));
                Query = queryObj;
 
                //Search only for current language
                if (AppSettings.CurrentSettings.Multilingual == true)
                {
                    TermQuery languageQuery = new TermQuery(new Term("Language", CultureInfo.CurrentUICulture.Name));
                    TermQuery languageNullQuery = new TermQuery(new Term("Language", SearchProvider.FieldNullValue));
 
                    BooleanQuery filterQuery = new BooleanQuery();
                    filterQuery.Add(languageQuery, BooleanClause.Occur.SHOULD);
                    filterQuery.Add(languageNullQuery, BooleanClause.Occur.SHOULD);
 
                    QueryFilter languageFilter = new QueryFilter(filterQuery);
 
                    this.hits = searcher.Search(queryObj, languageFilter);
                }
                else
                {
                    this.hits = searcher.Search(queryObj);
                }
 
                for (var iter = 0; iter < this.HitCount; iter++)
                {
                    var doc = this.hits.Doc(iter);
                }
            }
        }
        catch (Exception ex)
        {
            if (tryToFix && ex is ParseException)
            {
                this.query = this.TryFixQuery(this.query);
                this.ExecuteQuery(false);
            }
            else
            {
                this.error = ex;
                this.hits = null;
            }
        }
    }
 
    private Exception error;
    private string query;
    private IndexSearcher searcher;
    public void Dispose()
    {
        if (this.searcher != null)
        {
            this.searcher.Close();
            this.searcher = null;
        }
    }
}



Note that steps  3 and 4  will be changed at some point to be able to achieve this in less steps and less code. 


progress-logo

The Progress Team

View all posts from The Progress Team on the Progress blog. Connect with us about all things application development and deployment, data integration and digital business.

Comments

Comments are disabled in preview mode.
Topics

Sitefinity Training and Certification Now Available.

Let our experts teach you how to use Sitefinity's best-in-class features to deliver compelling digital experiences.

Learn More
Latest Stories
in Your Inbox

Subscribe to get all the news, info and tutorials you need to build better business apps and sites

Loading animation