Как я могу использовать предикат Buider для Sitecore Lucene Search

Я работаю над Sitecore 8.1 и реализую функциональность фильтра для одной из страниц от Sitecore lucene. FOT-фильтр Я использую предикат строитель. У меня есть 3 поля мультисписков на деталях

  1. Товар
  2. категория
  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.

Еще раз спасибо всем за помощь!

Другие вопросы по тегам