If you are using Find to index your content, you likely have used the Find Indexing job – which would index everything in one go. Today I stumped upon this question – A way to run indexing job for Commerce only | Optimizely Develope – and it is a good one – if you have many of content in CMS side, and they don’t change that often, if at all – you certain don’t want to waste time and resource in trying to reindex them again. Is there away to just index catalog content?
Yes, there is. It is a bit hacky solution, but it can certain work. But first, let’s dive in on how Find indexing job does it work. It relies on IIndexingJobService
, which itself relies on ContentIndex
er to do the job. In its turn, ContentIndexer
uses a list of IReindexInformation
to know which content to index, and in which languages. Here’s what it looks like
public interface IReindexInformation
{
/// <summary>
/// Content links to be reindexed.
/// </summary>
IEnumerable<ReindexTarget> ReindexTargets { get; }
/// <summary>
/// Gets the root to index.
/// </summary>
ContentReference Root { get; }
}
It has one Root
, and multiple ReindexTarget
, which contains
public class ReindexTarget
{
/// <summary>
/// The content references.
/// </summary>
public IEnumerable<ContentReference> ContentLinks { get; set; }
/// <summary>
/// The languages the collection of <see cref="ContentReference"/> are enabled on.
/// </summary>
public IEnumerable<CultureInfo> Languages { get; set; }
/// <summary>
/// The site that the collection of <see cref="ContentReference"/> appears on
/// or <c>null</c> if unknown.
/// </summary>
public SiteDefinition SiteDefinition { get; set; }
}
As you might have guessed, Commerce has its own IReindexInformation
to index catalog content. If we can only use that to run our job. This is how our “hack” begins
The interface IContentIndexer
has no method to control the IReindexInformation`
, but the default implementation ContentIndexer
does. We set it to the only one we need, so here it is
List<IReindexInformation> targets;
var contentIndexer = _contentIndexer as ContentIndexer;
if (contentIndexer != null)
{
targets = contentIndexer.ReindexInformation.ToList();
var commerceReIndexInformation = targets.FirstOrDefault(x => x.GetType() == typeof(CommerceReIndexInformation));
contentIndexer.ReindexInformation = new List<IReindexInformation>() { commerceReIndexInformation };
_indexingJobService.Start(OnStatusChanged);
contentIndexer.ReindexInformation = targets;
}
A note is that you will still see the “Indexing Global assets and other data” message, because IIndexingJobService
implementation will go through all SiteDefinition regardless and show that message, but the internal ContentIndexer
will skip if the SiteDefinition
passed to it does not match the SiteDefinition
in the IReindexInformation
(and for CommerceReIndexInformation
it’s SiteDefinition.Empty
As I mentioned in the beginning, this is a bit hacky solution, as you have to cast IContentIndexer
to its concrete implementation. The proper solution would be implement IContentIndexer
yourself. Given that’s not a trivial job, I’ll leave at that.