Sitecore 7 – Query items that inherits a template

Finally I’ve got a few hours to play with Sitcore 7 and its new LINQ interface to Solr/Lucene. Love it!

Computed index fields are really helpful to speed up things and make things easier. Some fields are enabled by default, but there are also a few pre-configured ones that are disabled by default in the DefaultIndexConfiguration.

One that caught my eye was the “_templates” field. It stores the collection of base templates of an item. It can for example be used for finding items of a specific type, or items that inherits this type. It’s disabled by default, so you have to enable it and rebuild the index.

I soon realised though that the “_templates” field just contains the list from Item.Template.BaseTemplates (plus Item.Template of course). I don’t know yet if this is by design – Sitecore 7 is stil just a preview.

If you need to query items that really inherits a template, you can use the example below. I wrote a simple ComputedIndexField that recurses through all templates, but stops on StandardTemplate. I haven’t found any case where I want to go above that, and it’ll speed up indexing a bit by stopping there.

public class InheritedTemplates : IComputedIndexField
{
    public string FieldName { get; set; }

    public string ReturnType { get; set; }

    public object ComputeFieldValue(IIndexable indexable)
    {
        return GetAllTemplates(indexable as SitecoreIndexableItem);
    }

    private static List<string> GetAllTemplates(Item item)
    {
        Assert.ArgumentNotNull(item, "item");
        Assert.IsNotNull(item.Template, "Item template not found.");
        var list = new List<string> { IdHelper.NormalizeGuid(item.TemplateID) };
        RecurseTemplates(list, item.Template);
        return list;
    }

    private static void RecurseTemplates(List<string> list, TemplateItem template)
    {
        foreach (var baseTemplateItem in template.BaseTemplates)
        {
            list.Add(IdHelper.NormalizeGuid(baseTemplateItem.ID));
            if (baseTemplateItem.ID != TemplateIDs.StandardTemplate)
                RecurseTemplates(list, baseTemplateItem);
        }
    }
}

Then you can patch in this in your crawler configuration like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <contentSearch>
      <configuration type="Sitecore.ContentSearch.LuceneProvider.LuceneSearchConfiguration, Sitecore.ContentSearch.LuceneProvider">
        <DefaultIndexConfiguration type="Sitecore.ContentSearch.LuceneProvider.LuceneIndexConfiguration, Sitecore.ContentSearch.LuceneProvider">
          <fields hint="raw:AddComputedIndexField">
            <field fieldName="_alltemplates" storageType="yes" indexType="untokenized">Your.Namespace.InheritedTemplates, Your.Assembly</field>
          </fields>
        </DefaultIndexConfiguration>
      </configuration>
    </contentSearch>
  </sitecore>
</configuration>