Как получить все PageTemplate, который содержит определенный компонент?
У меня есть шаблон страницы ArticlePageTemplate
, это ArticlePageTemplate
содержит компонент под названием Articles
, Article
компонент имеет поле данных под названием Header
, SubHeader
, Date
, а также Content
,
Детали презентации ArticlesPageTemplate
Использование Lucene в sitecore 8. Как получить весь ArticlePageTemplate, содержащий компонент Article со значением "News" в подзаголовке компонента Article.
Структура сайта:
Вот мой код
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
используя код выше, но я не могу отфильтровать его, чтобы получить только те, ArticlePageTemplate
который содержит Article
компонент, в котором Article
подзаголовок компонента - "новости".
Я не знаю, как получить компонент статей ArticlePageTemplate
чтобы я мог добавить их к своему поисковому запросу в Lucene.
Любой совет приветствуется.
Замечания:
Источник данных ArticlesComponent
может измениться, так что это не всегда ребенок ArticlesPageTemplate
,
ОБНОВЛЕНИЕ (11.09.2015)
Я попробовал то, что предложил Ричард, но это не работает.
var articles = SearchService
.PerformSearch<ArticleResultItem>("/sitecore/content", "ArticlePageTemplate")
.Where(item => item.SubHeader == "News").ToList();
Использование приведенного выше запроса не дает никакого результата, но использование приведенного ниже запроса возвращает результат, но он возвращает ArticleComponent вместо ArticlePageTemplate.
var articles = SearchService
.PerformSearch<ArticleResultItem>("/sitecore/content"
.Where(item => item.SubHeader == "News").ToList();
РЕШЕНИЕ:
Вычисленные поля работают. Смотрите VisualizationField.cs по ссылке ниже:
2 ответа
Я вижу два подхода, которые вы можете использовать здесь:
Создайте "вычисляемое поле" для поля подзаголовка компонента Article. Вы должны настроить это так, чтобы индекс был настроен для поиска этого компонента в элементе с шаблоном ArticlePageTemplate и вычисления значения подзаголовка в индексе. По сути, это заставляет индекс думать, что поле подзаголовка на самом деле является полем элемента ArticlePageTemplate. Затем вы можете сделать обычный поиск по индексу.
Найдите справочные страницы для компонента. В этом сценарии вы выполняете поиск компонентов в индексе (не ArticlePageTemplate), и если вы можете зависеть от структуры вашей папки и не можете повторно использовать ее на разных страницах, вы можете просто получить родительскую страницу любого результата поиска. (item.Parent.Parent, в вашем примере структуры)
ОБНОВЛЕНИЕ: Некоторые ссылки для вычисляемых полей:
Вам нужно будет создать собственный класс, который позволит вам фильтровать по вашему полю, вы можете основывать его на SearchResultItem
учебный класс.
Так что-то вроде:
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....
}
}