Фильтрация элементов в SearchResultCollection
Я построил функцию, в которой я передаю строку стран, которые я хочу найти, и количество статей, которые я хочу получить из результатов поиска.
Но когда поиск возвращается из элементов содержимого Sitecore, я не хочу показывать элементы, отмеченные звездочкой (*), в начале их поля заголовка. Вот имя функции:
protected IEnumerable<Item> ShowHomePageNews(int numOfArticles, string stringofCountries)
{
List<Item> items = new List<Item>();
Sitecore.Search.Index indx = SearchManager.GetIndex("my_index_name");
using (IndexSearchContext searchContext = indx.CreateSearchContext())
{
CombinedQuery query = new CombinedQuery();
QueryBase catQuery = new FieldQuery("countries", stringofCountries); //FieldName, FieldValue.
SearchHits results = searchContext.Search(catQuery); //Searching the content items by fields.
SearchResultCollection result = results.FetchResults(0, numOfArticles);
foreach (SearchResult i in result)
{
Lucene.Net.Documents.Field url = i.Document.GetField("_url");
Sitecore.Data.ItemUri itemUri = new Sitecore.Data.ItemUri(url.StringValue());
Sitecore.Data.Items.Item item = Sitecore.Context.Database.GetItem(itemUri.ToDataUri());
items.Add(item);
}
}
return items;
}
И я вызываю эту функцию в моем PageLoad:
rptHomePageNews.DataSource = ShowHomePageNews (4, "США");
И это моя разметка:
<asp:Panel ID="HomePageNews" runat="server">
<asp:Repeater ID="rptHomePageNews" runat="server">
<ItemTemplate>
<li>
<%--<sc:FieldRenderer ID="FieldRenderer1" FieldName="Date" runat="server" Item="<%# Container.DataItem as Sitecore.Data.Items.Item %>" />--%>
<a href="<%# Sitecore.Links.LinkManager.GetItemUrl(Container.DataItem as Sitecore.Data.Items.Item) %>">
<sc:FieldRenderer ID="FieldRenderer2" FieldName="Title" runat="server" Item="<%# Container.DataItem as Sitecore.Data.Items.Item %>" />
</a>
</li>
</ItemTemplate>
</asp:Repeater>
Какие изменения я должен сделать в моей функции ShowHomePageNews?
2 ответа
Один из подходов здесь - выполнить пост-фильтрацию с использованием запроса LINQ, что-то вроде этого:
string myTitleField = "My Title Field";
List<Item> results = items.Where(x => x.Fields[myTitleField].Value.Contains("*") == false).ToList();
Это неэффективно, так как вам нужно будет загрузить все элементы перед началом фильтрации. Если эффективность не имеет значения, то, по крайней мере, это обеспечивает простой способ фильтрации.
Однако я предлагаю добавить поле в индекс и пометить запись значением, которое вы можете фильтровать (например, "TitleContainsAsterisk"). Затем вы можете изменить свой запрос, чтобы отфильтровать результаты, которые имеют "true" или "1" в этом поле.
EDIT (для Advanced Database Crawler) Пример конфигурации и кода для добавления динамического поля. Обратите внимание, что я не скомпилировал и не запустил это, я псевдокодирую из имеющегося у меня кода:
<dynamicFields hint="raw:AddDynamicFields">
<dynamicField type="MyNameSpace.TitleContainsAsterisk,MyBinary"
name="TitleContainsAsterisk" storageType="YES" indexType="TOKENIZED" vectorType="NO" boost="1f" />
</dynamicFields>
/// <summary>
/// Field Configuration (for the indexer) to index the if there is an asterisk in the title
/// </summary>
public class TitleContainsAsterisk: BaseDynamicField {
public override string ResolveValue(Item item) {
string myTitleField = "My Title Field";
bool containsAsterisk = item.Fields[myTitleField].Value.Contains("*");
return containsAsterisk ? "1" : "0";
}
}
Если вы счастливы использовать Linq, вы можете заменить цикл foreach на что-то вроде этого:
var db = Sitecore.Context.Database;
items = result
.Where(r => !r.Title.StartsWith("*"))
.Select(r => db.GetItem(new Sitecore.Data.ItemUri(r.Url).ToDataUri()))
.ToList();