Custom filter methods
Describes how to use custom filter methods in Optimizely Search & Navigation.
Use filters to narrow down search results and to add advanced search functionality to websites. The Optimizely Search & Navigation fluent API provides a set of filter methods you can extend.
The Filter method provides a powerful way of filtering out certain matching documents by accepting an expression that returns a filter. Create these expressions by using extension methods, such as the Match
method. These extension methods are limited to operating on value types and strings but not on complex types. However, you can extend the filtering functionality in the following ways:
- Create a custom extension method that returns aÂ
FilterExpression
. - Create extension methods that return an instance of theÂ
DelegateFilterBuilder
 class.
Return a FilterExpression
A FilterExpression
is an object that encapsulates an expression that returns a Filter. When you execute the query, it finds and replaces FilterExpression
by the expression it encapsulates. Finally, it replaces the field names in that expression with the corresponding field names on the server side.
The following example shows two classes:Â Author
and BlogPost
.
public class Author {
public int Id {
get;
set;
}
public string Name {
get;
set;
}
}
public class BlogPost {
public string Title {
get;
set;
}
public Author {
get;
set;
}
}
Assume that you want to find blog posts that have authors. Without a custom extension method, you cannot do that directly because there is no Exists
method for the Author
type. However, you know that authors have an Id
(which is true because the Id
is a value type and is 0 if not specified), so the following code can accomplish this.
client.Search<BlogPost>()
.Filter(x => x.Author.Id.Exists());
Adding a custom extension method can make queries like this more convenient.
public static class AuthorFilters {
public static FilterExpression<Author> Exists(this Author author) {
return new FilterExpression<Author>(x => x.Id.Exists());
}
}
Next, rewrite the original query to check for the existence of an author instead of the existence of the author ID.
client.Search<BlogPost>()
.Filter(x => x.Author.Exists());
Alternatively, add a custom method for the BlogPost
class.
public static class BlogPostFilters
{
public static FilterExpression<BlogPost> HasAuthor(this BlogPost blogPost)
{
return new FilterExpression<BlogPost>(x => x.Author.Id.Exists());
}
}
Then, your query can be:
client.Search<BlogPost>()
.Filter(x => x.HasAuthor());
Extending the filtering functionality by creating extension methods that return FilterExpression
is not limited to checking for existence or to single filters. Assuming that a user logs in and a publication date exists on the BlogPost
class, you can create a custom method for finding blog posts visible to the user.
public static class BlogPostFilters {
public static FilterExpression<BlogPost> VisibleToUser(this BlogPost blogPost, User user) {
return new FilterExpression<BlogPost> (x => x.PublicationDate.InRange(DateTime.Now, DateTime.MaxValue) |
x.Author.Id.Match(user.Id));
}
}
Return a DelegateFilterBuilder
Extension methods returning an instance of DelegateFilterBuilder
are one level closer because the DelegateFilterBuilder
constructor requires an expression that returns an actual filter, which means they are not as useful for extending the filtering functionality for complex types. Instead, they are useful for extending the filtering functionality using filters not exposed by the fluent API.
Updated 6 months ago