Как я могу использовать предикат Buider для Sitecore Lucene Search
Я работаю над Sitecore 8.1 и реализую функциональность фильтра для одной из страниц от Sitecore lucene. FOT-фильтр Я использую предикат строитель. У меня есть 3 поля мультисписков на деталях
- Товар
- категория
- Сервисы
Теперь на странице со списком у меня есть все три группы фильтров в виде флажков, как показано на рисунке ниже -
Моё требование - я хочу применить Или между внутри группы, как между продуктами должно быть условие И, и между двумя группами должно быть условие А. Например, продукты и категории должны быть А.
Я следил за публикацией в блоге http://getfishtank.ca/blog/building-dynamic-content-search-linq-queries-in-sitecore-7
Чтобы добиться этого, что я пытаюсь -
var builder = PredicateBuilder.True<TestResultItem>();
var Categorybuilder = PredicateBuilder.False<TestResultItem>();
if (!string.IsNullOrEmpty(Categorys))
{
var CategoryItems = Categorys.Split('|');
foreach (var Category in CategoryItems)
{
var ct = Sitecore.ContentSearch.Utilities.IdHelper.NormalizeGuid(Categorys, true);
Categorybuilder = Categorybuilder.Or(i => i.Category.Contains(ct));
}
}
var Servicebuilder = PredicateBuilder.False<TestResultItem>();
if (!string.IsNullOrEmpty(Service))
{
var ServiceItems = Service.Split('|');
foreach (var ser in ServiceItems)
{
var si = Sitecore.ContentSearch.Utilities.IdHelper.NormalizeGuid(ser, true);
Servicebuilder = Servicebuilder.Or(i => i.Service.Contains(si));
}
}
var productsbuilder = PredicateBuilder.False<TestResultItem>();
if (!string.IsNullOrEmpty(products))
{
var productItems = products.Split('|');
foreach (var product in productItems)
{
var pd = Sitecore.ContentSearch.Utilities.IdHelper.NormalizeGuid(product, true);
productsbuilder = productsbuilder.Or(i => i.Category.Contains(pd));
}
}
Servicebuilder = Servicebuilder.Or(Categorybuilder);
productsbuilder = productsbuilder.Or(Servicebuilder);
builder = builder.And(productsbuilder);
Приведенный выше код не работает для меня. Я знаю, что я делаю что-то не так, потому что я плохо разбираюсь в построителе предикатов, или между группой флажков не работает условие.
Может кто-нибудь, пожалуйста, скажите мне, где я не прав в данном коде или каким-либо лучшим способом добиться этого.
Любая помощь будет оценена
3 ответа
Я недавно сделал нечто подобное, и это работает так:
Создайте свои предикаты "или":
var tagPredicate = PredicateBuilder.False<BlogItem>();
tagPredicate = tagValues.Aggregate(tagPredicate, (current, tag) => current.Or(p => p.Tags.Contains(tag)))
где tagValues - это IEnumerable, содержащий нормализованные направляющие.
Я делаю это для нескольких списков гидов. В конце я обертываю их так:
var predicate = PredicateBuilder.True<BlogItem>();
predicate = predicate.And(tagPredicate);
predicate = predicate.And(...);
Глядя на ваш код: прежде всего изменить
Servicebuilder = Servicebuilder.Or(Categorybuilder);
productsbuilder = productsbuilder.Or(Servicebuilder);
builder = builder.And(productsbuilder);
в
builder = builder.And(Categorybuilder);
builder = builder.And(Servicebuilder);
builder = builder.And(productsbuilder);
У вас должен быть один основной предикат, чтобы объединить фильтры с условием И и другими предикатами (например, для категорий, услуг или продуктов), чтобы объединить фильтры внутри с условием ИЛИ.
// This is your main predicate builder
var builder = PredicateBuilder.True<TestResultItem>();
var Categorybuilder = PredicateBuilder.False<TestResultItem>();
var Servicebuilder = PredicateBuilder.False<TestResultItem>();
var productsbuilder = PredicateBuilder.False<TestResultItem>();
builder = builder.And(Categorybuilder);
builder = builder.And(Servicebuilder);
builder = builder.And(productsbuilder);
Надеюсь, что это поможет вам.
Спасибо всем за предоставленную информацию -
Я обновил код в соответствии с вашими данными и теперь он работает. В моем старом коде произошли два изменения: одно: сборщик для multilist должен находиться внутри оператора if, а также добавление вновь созданного сборщика в основной сборщик в том же месте (внутри оператора if) -
Я делюсь приведенным ниже кодом, так что если кто-то захочет использовать его, он может легко скопировать отсюда -
var builder = PredicateBuilder.True<TestResultItem>();
if (!string.IsNullOrEmpty(Categorys))
{ var Categorybuilder = PredicateBuilder.False<TestResultItem>();
var CategoryItems = Categorys.Split('|');
foreach (var Category in CategoryItems)
{
var ct = Sitecore.ContentSearch.Utilities.IdHelper.NormalizeGuid(Categorys, true);
Categorybuilder = Categorybuilder.Or(i => i.Category.Contains(ct));
}
builder = builder.And(Categorybuilder);
}
if (!string.IsNullOrEmpty(Service))
{
var Servicebuilder = PredicateBuilder.False<TestResultItem>();
var ServiceItems = Service.Split('|');
foreach (var ser in ServiceItems)
{
var si = Sitecore.ContentSearch.Utilities.IdHelper.NormalizeGuid(ser, true);
Servicebuilder = Servicebuilder.Or(i => i.Service.Contains(si));
}
builder = builder.And(Servicebuilder);
}
if (!string.IsNullOrEmpty(products))
{
var productsbuilder = PredicateBuilder.False<TestResultItem>();
var productItems = products.Split('|');
foreach (var product in productItems)
{
var pd = Sitecore.ContentSearch.Utilities.IdHelper.NormalizeGuid(product, true);
productsbuilder = productsbuilder.Or(i => i.Category.Contains(pd));
}
builder = builder.And(productsbuilder);
}
В приведенном выше коде категории "Сервис" и "продукты" являются значениями, разделенными конвейерами, которые поступают из поля многостраничного списка Sitecore.
Еще раз спасибо всем за помощь!