如何获取包含特定组件的所有 PageTemplate?

How to get all PageTemplate that contains a specific component?

我有一个名为 ArticlePageTemplate 的页面模板。此 ArticlePageTemplate 包含一个名为 Articles 的组件。 Article 组件具有名为 HeaderSubHeaderDateContent 的数据字段。

ArticlesPageTemplate

的演示文稿详情

在 sitecore 8 中使用 Lucene。如何获取所有包含 Article 组件的 ArticlePageTemplate,其中 Article 组件的子标题中的值为 "News"。

站点核心结构:

这是我的代码

public class LuceneSearchService : ILuceneSearchService, IDisposable
{
    bool disposed = false;
    // Instantiate a SafeHandle instance.
    SafeHandle handle = new SafeFileHandle(IntPtr.Zero, true);

    private IProviderSearchContext _SearchContext;
    private ISearchIndex _Index;

    private string _IndexName = "sitecore_web_index";

    public string IndexName
    {
        get { return _IndexName; }
        set { _IndexName = value; }
    }


    public LuceneSearchService()
    {
        _Index = ContentSearchManager.GetIndex(this.IndexName);
        _SearchContext = _Index.CreateSearchContext();
    }

    public IQueryable<SearchResultItem> PerformSearch(string searchPath)
    {

        var searchQuery = _SearchContext.GetQueryable<SearchResultItem>()
        .Where(i => i.Path.StartsWith(searchPath));

        return searchQuery;

    }

    public IQueryable<SearchResultItem> PerformSearch(string searchPath, string templateName)
    {
        var searchQuery = PerformSearch(searchPath).Where(x => x.TemplateName == templateName);

        return searchQuery;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);            
    }

    // Protected implementation of Dispose pattern. 
    protected virtual void Dispose(bool disposing)
    {
        if (disposed)
            return;

        if (disposing)
        {
            handle.Dispose();
            _SearchContext.Dispose();
            _Index.Dispose();
        }

        // Free any unmanaged objects here. 
        //
        disposed = true;
    }
}

代码实现

public void SearchArticles()
    {
        var articles = SearchService.PerformSearch("/sitecore/content", "ArticlePageTemplate").ToList();
        foreach (var article in articles){
            var articleName = article;
        }


    }

我可以使用上面的代码获取所有 ArticlesPageTemplate,但我无法过滤它以仅获取那些包含 Article 组件的 ArticlePageTemplate,其中 Article 组件的副标题是 "news"。

我不知道如何获取 ArticlePageTemplate 的文章组件,因此我可以将它们添加到我在 lucene 中的搜索查询中。

如有任何建议,我们将不胜感激。

注:

ArticlesComponent 的数据源可能会更改,因此它并不总是 ArticlesPageTemplate 的 child。

更新(2015 年 9 月 11 日)

我尝试了 Richard 建议的方法,但没有用。

var articles = SearchService
        .PerformSearch<ArticleResultItem>("/sitecore/content", "ArticlePageTemplate")
        .Where(item => item.SubHeader == "News").ToList();

使用上面的查询不会产生任何结果,但使用下面的查询 returns 会得到结果,但它检索的是 ArticleComponent 而不是 ArticlePageTemplate。

var articles = SearchService
        .PerformSearch<ArticleResultItem>("/sitecore/content"
        .Where(item => item.SubHeader == "News").ToList();

解决方案:

计算字段有效。请参阅下面 link 中的 VisualizationField.cs:

https://gist.github.com/techphoria414/7604814

您需要创建一个自定义 class 允许您在您的字段上进行过滤,您可以将其基于 SearchResultItem class.

所以像这样:

public class ArticleResultItem : SearchResultItem
{
    [IndexField("SubHeader")]
    public string SubHeader { get;set; }
}

然后,如果您将 PerformSearch 方法更改为采用基于 SearchResultItem 的泛型,则可以在调用方法中使用该字段进行过滤。

public IQueryable<T> PerformSearch<T>(string searchPath)
    where T: SearchResultItem
{

    var searchQuery = _SearchContext.GetQueryable<T>()
    .Where(i => i.Path.StartsWith(searchPath));

    return searchQuery;

}

public IQueryable<T> PerformSearch<T>(string searchPath, string templateName)
    where T: SearchResultItem
{
    var searchQuery = PerformSearch<T>(searchPath).Where(x => x.TemplateName == templateName);

    return searchQuery;
}

然后你会这样称呼它:

public void SearchArticles()
{
    var articles = SearchService
        .PerformSearch<ArticleResultItem>("/sitecore/content", "ArticlePageTemplate")
        .Where(item => item.SubHeader == "News").ToList();
    foreach (var article in articles){
        var articleName = article;
        // Do something with the list here....
    }
}

我可以在这里看到两种方法:

  • 为 Article 组件子标题字段构建一个 'computed field'。 您可以设置它,以便将索引配置为查找该组件在具有 ArticlePageTemplate 模板的项目上,并将子标题值计算到索引中。这实质上使索引认为子标题字段实际上是 ArticlePageTemplate 项目上的一个字段。然后你可以在索引上做一个常规的搜索。

  • 查找组件的参考页。 在这种情况下,您搜索组件的索引(不是 ArticlePageTemplate),如果您可以依赖您的文件夹结构并且您没有 re-use 跨页面,然后您可以只抓取任何搜索结果的 parent 页面。 (item.Parent.Parent,在您的示例结构中)

更新:计算字段的一些链接: