We moved our Sitecore implementation to Solr 5.2.1 based on the issues we had faced with Lucene as described in my blog Lucene vs Solr – benefits with Solr. After few months in the implementation we realized we need to come-up with a better naming convention to maintain & manage large number Solr collections – hence decided to change the Solr collection names. For the new Search index configuration things were fine, and we were able to index them fine. But for existing Search Indexes after pointing them to new Solr collection – we were unable to index them and were getting below exception,
Exception Stack Trace – Job started: Index_Update_IndexName=sitecore_master_index_brand|#Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> Microsoft.Practices.ServiceLocation.ActivationException: Activation error occured while trying to get instance of type ISolrOperations`1, key "Prod_Brand_Master_sec" ---> Castle.MicroKernel.ComponentNotFoundException: Requested component named 'Prod_Brand_Master_sec' was not found in the container. Did you forget to register it? There are 45 other components supporting requested service 'SolrNet.ISolrOperations`1[[System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=188.8.131.52, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Object, mscorlib, Version=184.108.40.206, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=220.127.116.11, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'. Were you looking for any of them? at Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(String key, Type service, IDictionary arguments, IReleasePolicy policy) at Castle.MicroKernel.DefaultKernel.Resolve(String key, Type service, IDictionary arguments) at Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key) --- End of inner exception stack trace --- at Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key) at Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance[TService](String key) at Sitecore.Support.ContentSearch.SolrProvider.SwitchOnRebuildSolrSearchIndex.Rebuild(Boolean resetIndex, Boolean optimizeOnComplete) --- End of inner exception stack trace --- at System.RuntimeMethodHandle.InvokeMethod(Object target, Object arguments, Signature sig, Boolean constructor) at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object parameters, Object arguments) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture) at System.Reflection.MethodBase.Invoke(Object obj, Object parameters) at (Object , Object ) at Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args) at Sitecore.Jobs.Job.ThreadEntry(Object state)
We were using SwitchOnRebuild – so that rebuilding does not affect the search index that is currently used and also providing high availability to the sites / applications. The typical configuration looks like this,
<index id="sitecore_master_index_brand" type="Sitecore.ContentSearch.SolrProvider.SwitchOnRebuildSolrSearchIndex,Sitecore.ContentSearch.SolrSearchProvider"> <param desc="name">$(id)</param> <param patch:after="*[@desc='name']" desc="mainalias">ProdBrandMasterMain</param> <param patch:after="*[@desc='mainalias']" desc="rebuildalias">ProdBrandMasterRebuild</param> <param patch:after="*[@desc='rebuildalias']" desc="collection">Prod_Brand_Master</param> <param patch:after="*[@desc='collection']" desc="rebuildcollection">Prod_Brand_Master_sec</param> <!-- This initializes index property store. Id has to be set to the index id --> <param desc="propertyStore" ref="contentSearch/databasePropertyStore" param1="$(id)" /> <configuration ref="contentSearch/indexConfigurations/BrandComContentSolrIndexConfiguration" /> <strategies hint="list:AddStrategy"> <!-- NOTE: order of these is controls the execution order --> <strategy ref="contentSearch/indexUpdateStrategies/intervalAsyncMaster" /> </strategies> <locations hint="list:AddCrawler"> <crawler type="Sitecore.Support.ContentSearch.SitecoreItemCrawler, Sitecore.Support.107856"> <Database>master</Database> <Root>/sitecore/Content/Brand</Root> </crawler> </locations> </index>
This logically means,
|Sitecore Index||Solr Alias||Solr Collection|
|sitecore_master_index_brand||mainalias – ProdBrandMasterMain||Prod_Brand_Master|
|rebuildalias – ProdBrandMasterRebuild||Prod_Brand_Master_sec|
At any point of time sitecore_master_index_brand will using either collection Prod_Brand_Master or Prod_Brand_Master_sec or this gets switched every time when full rebuild is done.
Now comes the next question – where does the Sitecore maintains the active collection and rebuild collection, so that it alternatively switches between them. The answer is – this is maintained in Core Database Properties table through keys Active_Collection, Rebuild_Collection. It looks like this in Core DB, with the value representing the Solr collection name.
Coming back to the exception we received while re-indexing changing the Solr collection name in the index configuration – the issue was because of this mapping that is maintained in the Properties table. The mappings here were pointing to old collection names. The instructions from Sitecore support to handle this scenario is,
- Clean-up these entries in Core DB Properties table
- Recycle the application pool of your Sitecore instance
Once done, you will now be able to successfully re-index – as now in this case Properties table will get populated with mapping pointed to changed collection names.