diff --git a/src/Umbraco.Web/PublishedContentQuery.cs b/src/Umbraco.Web/PublishedContentQuery.cs index bfe8fb5260..a609a609b7 100644 --- a/src/Umbraco.Web/PublishedContentQuery.cs +++ b/src/Umbraco.Web/PublishedContentQuery.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Xml.XPath; @@ -224,14 +225,38 @@ namespace Umbraco.Web { var doc = cache.GetById(id); return doc; - } + } + + private static ConcurrentDictionary _guidToIntLoopkup; private IPublishedContent TypedDocumentById(Guid id, ContextualPublishedCache cache) - { - // todo: in v8, implement in a more efficient way - var legacyXml = UmbracoConfig.For.UmbracoSettings().Content.UseLegacyXmlSchema; - var xpath = legacyXml ? "//node [@key=$guid]" : "//* [@key=$guid]"; - var doc = cache.GetSingleByXPath(xpath, new XPathVariable("guid", id.ToString())); + { + // We create the lookup when we first need it + if (_guidToIntLoopkup == null) + _guidToIntLoopkup = new ConcurrentDictionary(); + + IPublishedContent doc; + + // Check if the lookup contains the GUID/INT value + if (_guidToIntLoopkup.TryGetValue(id, out int nodeId) == false) + { + // If not, then we perform an inefficient XPath for the GUID + + // todo: in v8, implement in a more efficient way + var legacyXml = UmbracoConfig.For.UmbracoSettings().Content.UseLegacyXmlSchema; + var xpath = legacyXml ? "//node[@key=$guid]" : "//*[@key=$guid]"; + doc = cache.GetSingleByXPath(xpath, new XPathVariable("guid", id.ToString())); + + // When we have the node, we add the GUID/INT value to the lookup + if (doc != null) + _guidToIntLoopkup.TryAdd(id, doc.Id); + } + else + { + // Otherwise we have the node id (INT) and can perform an efficient retrieval + doc = cache.GetById(nodeId); + } + return doc; }