Umbraco 7.3 - 无需使用 LINQ 即可找到 DocumentTypeAlias 的所有子项

Umbraco 7.3 - find all children of DocumentTypeAlias without having to dot your way through with LINQ

我有一个非常基本的例子:

string areaType = "PrivateHomes";

var plotProperties = Model.Content.AncestorOrSelf(1)
    .Children.Where(c => c.DocumentTypeAlias.Equals("Properties")).First()
    .Children.Where(c => c.Name == areaType).First()
    .Children.First()
    .Children.First();

foreach(var child in plotProperties.Children())
{ /* Do stuff */ }

此代码似乎...适得其反...不知何故...我的目标是获得名为“PrivateHomes”的 DocumentType“Types”的子级 - 有没有办法在不执行我的操作的情况下实现此目的在这里做什么?上面的代码有效,但我无法评估它的影响。

像 Model.Root().Descendants("Types").Where(x => x.Name == "PrivateHomes") 这样的东西怎么样?

https://our.umbraco.com/documentation/reference/templating/mvc/querying#traversing

有很多选择,但这里有一些有趣的选择,排名不分先后。

选项 1:TypedContentAtXPath
我真的很喜欢这种方法。这是我在 Umbraco 7 中的首选。在 Umbraco 7 中,发布的内容被缓存为 xml。您可以探索 /App_Data/umbraco.config 中的 xml 来感受它的形状。您也可以像这样使用 XPATH 查询它:

var privateHomesNode = Umbraco.TypedContentSingleAtXPath("//Properties/*[@nodeName='PrivateHomes'");

选项 2:XPathNavigator
这个选项写起来没那么有趣,但运行起来非常快。当我的目标是检索一个值而不是整个模型时,我偶尔喜欢使用此选项。

var navigator = UmbracoContext.Current.ContentCache.GetXPathNavigator();
var privateHomesExpression = navigator.Compile("root//Properties//*[@nodeName='PrivateHomes']");
var firstPrivateHome = navigator.SelectSingleNode(privateHomesExpression);
var firstPrivateHomeId = firstPrivateHome?.GetAttribute("id", "")

选项 3:UmbracoHelper 上的类似 Linq 的扩展
这是您正在尝试的选项。有很多不同的方法可以做到这些。如果您使用的是 ModelsBuilder,您也可以在查询中使用强类型模型。你可以使用 .Descendants() 但你必须非常小心。它可以很快变成一个代价高昂的查询。您可能会花费大量时间从根本不想检索的数据中构建 IPublishedContent 模型。

var privateHomesNode = Model.Content.AncestorOrSelf(1)
    .Children<CategoryPage>().First()
    .Children.First(c => c.Name == "PrivateHomes");

选项 4:检查查询
查询检查的方法有很多种。您可以执行简单的 TypedSearch,例如 Umbraco.TypedSearch("PrivateHomes"),但这可能 return 结果不是您想要的。你可以像这样做更复杂的事情:

var externalSearcher = ExamineManager.Instance.SearchProviderCollection["externalSearcher"];
var searchCriteria = _internalSearcher.CreateSearchCriteria();
var query = searchCriteria.RawQuery("nodeName:PrivateHomes");
var results = _internalSearcher.Search(query);

你最想避免的事情就是在你能帮助的时候使用 .Descendants()。我们在 2017 年对查询内容的不同方式进行了一些基准测试。它不是非常彻底,但我们的发现之一是使用 .Descendants() 的查询可能非常慢:Model.Content.AncestorOrSelf(1).DescendantsOrSelf().Where(c => c.IsDocumentType("myDocType"))。当我们 运行 重复上述查询时,结果会更好,因为 Umbraco 最终会将结果缓存在内存中。我们发现像 Umbraco.TypedContentAtXPath("//myDocType") 这样的 XPath 查询并没有经历第一次初始缓慢加载。我相信这是因为 XPath 查询不会花时间从所有中间结果构建 IPublishedContent 模型。