2

I am converting the Lucene Search to SOLR while migrating the project from Sitecore version 8.2 to 10.2.

In the current Sitecore version 8.2 of the project Lucene is implemented. I have updated the configuration and all most code-related changes. But in a few of the indexes, there are some custom fields added in Lucene in the schema on SitecoreItemCrawler.

<index id="project_career_master" type="Sitecore.ContentSearch.SolrProvider.SolrSearchIndex, Sitecore.ContentSearch.SolrProvider">
    <param desc="name">$(id)</param>
    <param desc="core">$(id)</param>
    <param desc="propertyStore" ref="contentSearch/indexConfigurations/databasePropertyStore" param1="$(id)" />
    <configuration ref="contentSearch/indexConfigurations/defaultSolrIndexConfiguration" >
        <enableReadAccessIndexing>true</enableReadAccessIndexing>
    </configuration>
    <strategies hint="list:AddStrategy">
        <strategy ref="contentSearch/indexConfigurations/indexUpdateStrategies/onPublishEndAsync" />
    </strategies>
    <locations hint="list:AddCrawler">
        <crawler type="project.Website.Indexes.Career.CustomCareerSearchCrawler, project.Website">
            <Database>master</Database>
            <Root>/sitecore/content/project/Careers</Root>
            <Templates>{BB39C081-385F-1421-9T68-70C0RT12DA00}</Templates>
        </crawler>
    </locations>
</index>

Here in the above configuration, you can see there is a custom crawler written:

<crawler type="project.Website.Indexes.Career.CustomCareerSearchCrawler, project.Website">

Backend Code:

using Lucene.Net.Documents;

    public class CustomCareerSearchCrawler : SitecoreItemCrawler
    {
        public readonly List<ID> _templateIDs = new List<ID>();
        public string Templates { get; set; }
        public string LanguageName { get; set; }

        public override void Initialize(ISearchIndex searchIndex)
        {
            Assert.IsNotNullOrEmpty(Templates, "TemplateIDs");
            var ids = Templates.Split('|');
            _templateIDs.Clear();
            foreach (var id in ids)
            {
                _templateIDs.Add(new ID(id));
            }

            base.Operations = new CustomIndexOperations()
            {
                TemplateIDs = this._templateIDs,
                SearchIndex = searchIndex
            };
            base.Initialize(searchIndex);
        }
    }

    public class CustomIndexOperations : IIndexOperations
    {
        public void Add(IIndexable indexable, IProviderUpdateContext context, ProviderIndexConfiguration indexConfiguration)
        {
            var item = (Item)(indexable as SitecoreIndexableItem);
            if (!TemplateIDs.Contains(item.TemplateID))
            {
                return;
            }          

            var document = new Document();
            document.Add(new Field("_uniqueid", indexable.UniqueId.Value.ToString(), Field.Store.YES, Field.Index.ANALYZED));
            document.Add(new Field("_datasource", indexable.DataSource.ToLowerInvariant(), Field.Store.YES, Field.Index.ANALYZED));
            document.Add(new Field("_indexname", SearchIndex.Name.ToLowerInvariant(), Field.Store.YES, Field.Index.ANALYZED));
            document.Add(new Field("_content", string.Format("{0}|{1}", item.Name, item.ID.ToString()), Field.Store.YES, Field.Index.ANALYZED));
            document.Add(new Field("_langauge", item.Language.Name, Field.Store.YES, Field.Index.NOT_ANALYZED));
            document.Add(new Field("_id", item.ID.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));
            document.Add(new Field("_name", item.Name, Field.Store.YES, Field.Index.NOT_ANALYZED));
            document.Add(new Field("_title", item["Job Position"], Field.Store.YES, Field.Index.NOT_ANALYZED));

            context.AddDocument(document, indexable.Culture != null ? new CultureExecutionContext(indexable.Culture) : null);
        }
    }

with the same, update and delete method also implemented on Crawler:

public void Update(IIndexable indexable, IProviderUpdateContext context, ProviderIndexConfiguration indexConfiguration)

public void Delete(IIndexableUniqueId indexableUniqueId, IProviderUpdateContext context)

The above backend code is using the Lucene DLL.

I want to implement the same in SOLR, does anyone has inputs for the same, how to rewrite the above backend code in SOLR, please?

3
  • 1
    Does it need to be a similar approach with custom add/edit/delete? I think you could achieve the same result (i.e. custom index only containing specific templates + remove those with date passed). by using a combination of < include hint="list:AddIncludedTemplate" > to select templates and < fields hint="raw:AddComputedIndexField" > to set master item as unpublishable. Oct 11, 2022 at 6:08
  • Thanks, Dean Obrien. I was also thinking of the same but it's a 6-year-old project and I do not know what is the exact purpose of this code. It's a multilingual website. In other indexes, the code is written the same as you described. In Sitecore SOLR the way to add a custom field is described here: doc.sitecore.com/xp/en/developers/102/… I am not able yet to decide which approach should I follow. Oct 11, 2022 at 6:46
  • 3
    I think your best approach would be to figure out what the exact needs are as I'm quite sure you will be able to achieve them without a custom crawler. Upgrading projects and code without knowing what they are actually doing is a recipe for disaster and will always lead to unmanageable legacy code bases. Nobody wants that...
    – Gatogordo
    Oct 11, 2022 at 7:14

1 Answer 1

2

To resolve the above issue and find the solution, I have explored Sitecore.ContentSearch DLL and found out it provides the below method in the IProviderUpdateContext interface.

void AddDocument(object itemToAdd, IExecutionContext executionContext);
void AddDocument(object itemToAdd, params IExecutionContext[] executionContexts);
void Delete(IIndexableUniqueId id, params IExecutionContext[] executionContexts);
void Delete(IIndexableId id, params IExecutionContext[] executionContexts);
void UpdateDocument(object itemToUpdate, object criteriaForUpdate, IExecutionContext executionContext);

In Sitecore 10.2 it takes a parameter object as a type of Dictionary. Hence I updated the code as mentioned below:

var document = new Dictionary<string, object>();
document.Add("_uniqueid", indexable.UniqueId.Value.ToString());
document.Add("_datasource", indexable.DataSource.ToLowerInvariant());
document.Add("_indexname", SearchIndex.Name.ToLowerInvariant());
document.Add("_content", string.Format("{0}|{1}", item.Name, item.ID.ToString()));
//other fields
context.AddDocument(document, indexable.Culture != null ? new CultureExecutionContext(indexable.Culture) : null);

After building and publishing the code it's working perfectly fine and I get the result into the SOLR query.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.