2
votes

I am working on Sitecore 8.1 and I am implementing filter functionality for one of the page by Sitecore lucene. Fot filtering I am using predicate builder. I have 3 multi-lists field on detail items

  1. Product
  2. Category
  3. Services

Now on listing page I have all three group filters as checkboxes as given in below image - enter image description here

My Requirement is I want to apply Or between inside the group like between products condition should be Or and between two groups condition should be And. For example products and Category should be And.

I followed http://getfishtank.ca/blog/building-dynamic-content-search-linq-queries-in-sitecore-7 blog post to implement this

To achieve this what I am trying -

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);

The above given code is not working for me. I know I am doing something wrong as I am not good with Predicate builder, Or condition is not working between check boxes group.

Can anyone please tell me where I am wrong in given code or any best way to achieve this.

Any help would be appreciated

3

3 Answers

1
votes

You need to have one main predicate to join filters with AND condition & other predicates (e.g. for categories or services or products) to join filters internally with OR condition.

// 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);

Hope this will help you.

1
votes

I did something similar recently and it works like this:

Create your "or" predicates:

var tagPredicate = PredicateBuilder.False<BlogItem>();
tagPredicate = tagValues.Aggregate(tagPredicate, (current, tag) => current.Or(p => p.Tags.Contains(tag)))

where tagValues is an IEnumerable containing the normalized guids.

I do this for several guid lists. In the end I wrap them together like this:

var predicate = PredicateBuilder.True<BlogItem>();
predicate = predicate.And(tagPredicate);
predicate = predicate.And(...);

Looking at your code: first of all change

Servicebuilder = Servicebuilder.Or(Categorybuilder);
productsbuilder = productsbuilder.Or(Servicebuilder);
builder = builder.And(productsbuilder);

into

builder = builder.And(Categorybuilder);
builder = builder.And(Servicebuilder);
builder = builder.And(productsbuilder);
0
votes

Thanks all for providing your inputs -

I updated the code as per your inputs and now it's working. There was two changes in my old code one was builder for multilist should be inside the if statement and also adding newly created builder to main builder on same location (inside the if statement) -

I am sharing the code below so that if anyone want to use it he can easily copy from here -

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);
}

In the above code Categorys, Service and products are pipe separated values which are coming from Sitecore Multi-list field.

Thanks again everyone for help!!