Add filtersBuilders together

Vote:
 

as per this answer: 

https://world.episerver.com/forum/developer-forum/EPiServer-Search/Thread-Container/2016/11/multiple-filter-group/#172178

it appears that filters can be added together when filtering like so... 

.For(query).Filter(filterBuilder | HashfilterBuilder)

but when I try to add them together myself the compiler complains...

myFilterBuilder = myFilterBuilder | (MethodThatReturnsAFilterBuilder());

but the list of filters are going to be dynamic, a user could select any grouping of filters, and we've a central re-usable method that is expecting a single filterBuilder for filtering

How do i add filterBuilders together? Or achieve something that does the same thing?

#210542
Nov 27, 2019 11:41
Vote:
 

Hi Noel, 

If you only have the ability to add one single filter builder to the search method you're using, and the list of filtering can be dynamic as you say, couldn't you just encapsulate the chaining of filters in one single method?

By that I mean, one single method, inside this method you will call multiple other methods depending on the search request thats been made, that essentially take the current filter builder, and apply an .Or() filter expression, then simple pass the builder on. 

The way you're combining above won't work as you're attempting to assign the value of myFilterBuilder | (MethodThatReturnsAFilterBuilder(). - the use chaining like that can only be done when using the .Filter extension. 

Thanks,

Paul 

#210543
Nov 27, 2019 12:24
Vote:
 

Hi @Paul,

not quite sure what you mean, when I AND Filterbuilders it does not work as I expect....

// will not compile
var filterExpression = ServiceLocator.Current.GetInstance<IClient>().BuildFilter<myContentPage>();
var otherFilterExpression = ServiceLocator.Current.GetInstance<IClient>().BuildFilter<myContentPage>();
var allFilters = filterExpression.And(otherFilterExpression);

but I think casting to "Filter" may be the anwser...

// compiles but produces no results?? :-(
Filter filterExpression = ServiceLocator.Current.GetInstance<IClient>().BuildFilter<myContentPage>();

filterExpression = filterExpression & BuildTypeFilterExpression(submissionModel,  typeFilterCheckBoxes);
filterExpression = filterExpression & BuildStatusFilterExpression(submissionModel, statusFilterCheckBoxes);
filterExpression = filterExpression & GetYearFilter(submissionModel, out yearFilterCheckBoxes);

but "AND"ing with "&"  above doesn't produce any results, got excited when FilterBuilder casted to a Filter, but now search isn't working as expected.

#210548
Edited, Nov 27, 2019 12:58
Vote:
 

Hi Noel, 

Yeah you're using the extension method for the filter builder incorrectly - the .And extension is expecting an expression not another filter builder.

What I mean when I say encapsulate this into one method is, just have one wrapper method responsible for building your single filter builder, i.e.

public static FilterBuilder<IContent> GetMyBuilder(ITypeSearch<IContent> search)
        {
            FilterBuilder<IContent> builder = new FilterBuilder<IContent>(search.Client);
            builder = builder.ApplyAdditionalFiltering();

            return builder;
        }

This method uses an extension method that just chains additional filter expressions to the builder :

public static FilterBuilder<IContent> ApplyAdditionalFiltering(this FilterBuilder<IContent> builder)
        {
            builder = builder.Or(x => x.Name.Match("Something"));

            return builder;
        }

Pretty crude example but just to illustrate. 

Then when it comes to your search method which I believe you don't have the ability to change, you just use .Filter(builder) applying it. 

#210550
Nov 27, 2019 13:10
Vote:
 

Hey @Paul,

Ah ok I get you, actually, what you've got is exactly what I had, but the problem is i need this kinda structure...

OR ( AND AND AND) + OR (AND AND AND AND) ... etc

so if they search for a year + other stuff, that's "or this set of years" + "or this set of categories" + "or this other set of categories"

so yeah, what you got makes sense but where you have 

builder = builder.Or(x => x.Name.Match("Something"));

and need to do something more like...

groupedFilter = groupBuilder.And().And().And()
builder = builder.Or(groupedFilter); // 

#210551
Edited, Nov 27, 2019 13:19
Vote:
 

Actually, thinking about it, you could just chain the filter builders like this:

filterBuilder = filterBuilder.Or(x => yearsFilterBuilder).Or(x => categoryFilterBuilder);

Haven't tested it but pretty sure it will work!

#210553
Nov 27, 2019 13:42
Vote:
 

I eventually decided to change the central method to accept an array of FilterBuilders (List<FilterBuilders>), and I'm presuming calling .Filter() on each array item will have a total effect of an AND filter.

#210569
Nov 27, 2019 22:55
Vote:
 

Yeah exactly. Glad you got there anyway

#210578
Nov 28, 2019 13:02