Performance tip when using GetDescendents for catalog content

Mattias Olsson 2020-08-18 20:03:00

To load all catalog nodes for example, you would probably be tempted to use something similar to the following code:

public class CatalogContentLoader
{
    private readonly IContentLoader _contentLoader;
    private readonly ReferenceConverter _referenceConverter;

    public CatalogContentLoader(
        IContentLoader contentLoader,
        ReferenceConverter referenceConverter)
    {
        _contentLoader = contentLoader;
        _referenceConverter = referenceConverter;
    }

    public IEnumerable<NodeContent> GetAllNodes()
    {
        var allCatalogContentLinks = _contentLoader
            .GetDescendents(_referenceConverter.GetRootLink());
        return _contentLoader
            .GetItems(allCatalogContentLinks, CultureInfo.InvariantCulture)
            .OfType<NodeContent>();
    }
}

There is a better way through a performance perspective though. In the slightly modified code below, we filter the list of content links to only contain references to catalog nodes, which will probably reduce number of items to be fetched significantly:

public IEnumerable<NodeContent> GetAllNodes()
{
    var allCatalogNodeContentLinks = _contentLoader
        .GetDescendents(_referenceConverter.GetRootLink())
        .Where(x => IsCatalogContentType(x, CatalogContentType.CatalogNode));

    return _contentLoader
        .GetItems(allCatalogNodeContentLinks, CultureInfo.InvariantCulture)
        .OfType<NodeContent>();
}

private bool IsCatalogContentType(
    ContentReference contentLink,
    CatalogContentType catalogContentType)
{
    return _referenceConverter.GetContentType(contentLink) == catalogContentType;
}

If you want to fetch all variations you could instead filter on CatalogContentType.CatalogEntry. Probably not a huge performance improvement, but still:

public IEnumerable<VariationContent> GetAllVariants()
{
    var allCatalogEntryContentLinks = _contentLoader
        .GetDescendents(_referenceConverter.GetRootLink())
        .Where(x => IsCatalogContentType(x, CatalogContentType.CatalogEntry));

    return _contentLoader
        .GetItems(allCatalogEntryContentLinks, CultureInfo.InvariantCulture)
        .OfType<VariationContent>();
}