Content Relationships in Sitecore (using the Links Database)

Sometimes it is useful to identify relationships between items of content in Sitecore (related news items for example). This blog post explores a small set of extension methods to achieve this.

On our site we have news stories, these news stories can be related (Home News, People News etc), so how can this be relected in the content? Essentially I can see two ways: we can either tag the content with taxonomic terms and use an index or we can generate a list of news articles that are referred to by those terms. I will explore using a search index in another blog article, so for the moment I will just consider using the a list of referrers.

In Sitecore all content is an item: while something will have a path and (potentially) a url, ultimately it is uniquely identified by a GUID. Whitin the Administration interface of Sitecore references from one item to another can be explored by clicking on the “Links” button within the “Navigation” menu tab. For a normal content item this can be used to show references to the Template of the item and the Standard Values of the item (which are both, obviously, items), and by looking in the other direction it is possible to identify all of the uses (references) of a particular template among the content items.

This functionality is delivered by Sitecore using the Link database, which records item to item references.

We can use this database (and the Sitecore API) to gain the functionality that we need.

The easiest way to make this usable from a code point of view is to write an extension method (OK, three extensions methods), so that given an item, the items that refer to it can be readily identified. I added to extra methods to find referrers by template, and by any item descended from a particular template.

public static List<Item> GetReferrers(this Item item)
{
	var itemLinks = Globals.LinkDatabase.GetReferrers(item);
	return itemLinks
		.Select(itemLink => itemLink.GetSourceItem())
		.Where(referrerItem => referrerItem != null)
		.ToList();
}

public static List<Item> GetReferrersByTemplate(this Item item, Guid templateGuid)
{
	var templateId = new ID(templateGuid);
	return item.GetReferrers().Where(x => x.TemplateID == templateId).ToList();
}

public static List<Item> GetReferrersDescendsByTemplate(this Item item, Guid templateGuid)
{
	return item.GetReferrers().Where(x => x.DescendsFromTemplate(templateGuid)).ToList();
}

So in context this following code identifies the subset of taxonomic tags for a dropdown list including only those actually in use by News items:

private List<KeyValuePair<string, string>> GetTaxonomyTags(string folder, Guid itemTemplate)
{
	List<KeyValuePair<string, string>> taxonomyIds = new List<KeyValuePair<string, string>>();
	string taxonomyQuery = $"{folder}//*[@@templateid='{Constants.TemplateIds.TaxonomyTermId}']";

	Item[] taxonomyItems = _sitecoreContext.Database.SelectItems(taxonomyQuery);
	if (taxonomyItems.Any())
	{
		taxonomyIds.AddRange(taxonomyItems
			.Where(x => x.GetReferrersDescendsByTemplate(itemTemplate).Any())
			.Select(taxonomyItem =>
                         new KeyValuePair<string, string>(taxonomyItem.Name, taxonomyItem.Name)));
	}
	return taxonomyIds;
}