HomeDev guideRecipesAPI Reference
Dev guideUser GuidesLegal TermsNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev guide

Where filter

Describes filtering on a document using the Where method.

👍

Beta

The Optimizely Graph .NET Client is in beta. Contact your Customer Success Manager for information.

The Where method is built for the Where Filter condition for the query result.

The parameters for the Where method are:

  • A field name.
  • An instance of the IFilterOperator interface that is combined and transformed to an Optimizely Graph filter query.
var filterOperator = // create a concrete instance of IFilterOperator
new StringFilterOperators()
.Contains("value");

var query = queryBuilder
.ForType<MyDocument>()
  .Fields(x=>x.Property1, x=>x.Property2)
  .Where(x=>x.Property1, filterOperator)
 .ToQuery()
.BuildQueries();

There are four implementations of IFilterOperator:

  • NumericFilterOperators – The filter operators for the Number field type. Optimizely Graph supports integer and float type.
  • BooleanFilterOperators – The filter operators for the Boolean field type.
  • DateFilterOperators – Filter operators for the DateTime field type.
  • StringFilterOperators – Filter operators for the String field type.

Filter expression

The Optimizely Graph .NET Client supports built-in functions and boolean logical operators for the filter query. It is similar to the FIND client.

An example for filtering on an ArticlePage to show items where Name contains "Optimizely" AND Status is "Published":

var query = queryBuilder
.ForType<ArticlePage>()
  .Fields(x=>x.Name, x=>x.MetaDescription)
  .Where(x=>x.Name.Match(“Optimizely”) & x.Status.Eq("Published"))
.ToQuery()
.BuildQueries();

Boolean filter

  • AndFilter<T> class – Wrap one or more conditions with an AND operator. Use And method to combine many filters.
  • OrFilter<T> class – Wrap one or more conditions with an OR operator. Use Or method to combine many filters.
  • NotFilter<T> class – Wrap one or more conditions with an NOT operator. Use Not method to combine many filters.

You can create one of the preceding classes using the BooleanFilter class. Use static methods AndFilter(), OrFilter(), and NotFilter() to create AndFilter, OrFilter, and NotFilter instances respectively.


var andFilter = BooleanFilter
.AndFilter<HomePage>()
.And(x=>x.Name.Eq("Your page name"))
.And(x=>x.Status.Eq("Published"));

var query = queryBuilder
.ForType<ArticlePage>()
  .Fields(x=>x.Name, x=>x.MetaDescription)
  .Where(andFilter)
.ToQuery()
.BuildQueries();

You can use basic logical operators AND (&), OR (|), and NOT (!) for creating a boolean filter.

var andFilter = BooleanFilter
.AndFilter<HomePage>()
.And(x=>x.Name.Eq("Your page name"))
.And(x=>x.Status.Eq("Published"));

var query = queryBuilder
.ForType<ArticlePage>()
  .Fields(x=>x.Name, x=>x.MetaDescription)
  .Where(andFilter | x=>x.IsDraft.Eq(true)) // wrap OrFilter for combining 2 filters
.ToQuery()
.BuildQueries();

For the complex filter query, use a variable of filter operator.

IFilterOperator filterForField1 = //create filter operator for type of Field1
IFilterOperator filterForField2 = //create filter operator for type of Field2
IFilterOperator filterForField3 = //create filter operator for type of Field3

var query = queryBuilder
.ForType<MyDocument>()
  .Fields(x=>x.Property1, x=>x.Property2)
  .Where(x=> x.Field1, filterForField1)
  .Where(x=>x.Field2, filterForField2)
  .Where(x=>x.Field3, filterForField3)
.ToQuery()
.BuildQueries();

AND logic

When you use multiple filters on different fields, the AND logical is implicitly applied.

For example if you need filter on MyDocument where Field1.In(1,2,3) AND Field2.NotIn(4,5,6):

var query =  queryBuilder
.ForType<MyDocument>()
  .Where(x=> x.Field1.In(1,2,3))
  .Where(x=> x.Field2.NotIn(4,5,6))
.ToQuery()
.BuildQueries();

Multiple Where methods

Do not use multiple Where methods for filtering on the same field. For example:

var query = queryBuilder
.ForType<MyDocument>()
  .Fields(x=>x.Property1, x=>x.Property2)
  .Where(x=> x.Property1.InRange(1,9))
  .Where(x=> x.Property1.NotIn(4,5,6)) //invalid query
.ToQuery()
.BuildQueries();

Instead, there are other ways to build the same functionality:

Option 1 – Create an instance of IFilterOperator for multiple filters on one field:

var filter = new NumericFilterOperators()
  .InRange(1,9)
  .NotIn(4,5,6);

var query = queryBuilder
.ForType<MyDocument>()
  .Fields(x=>x.Property1, x=>x.Property2)
  .Where(x=>x.Property1, filter) //Passing an IFilterOperator for Property1
.ToQuery()
.BuildQueries();

Option 2 – Use boolean logic operators to wrap the conditions:

var andFilter = BooleanFilter
.AndFilter<MyDocument>()
.And(x=>x.Property1.InRange(1,9)/*condition1*/, x=> x.Property2.NotIn(4,5,6)/*condition2*/);

  var query = queryBuilder
  .ForType<MyDocument>()
    .Fields(x=>x.Property1, x=>x.Property2)
    .Where(andFilter)
  .ToQuery()
  .BuildQueries();
//Or maybe
var query = queryBuilder
.ForType<MyDocument>()
  .Fields(x=>x.Property1, x=>x.Property2)
  .Where(x=>x.Property1.InRange(1,9) & x=>x.Property1.NotIn(4,5,6))) //use AND logic condtional
.ToQuery()
.BuildQueries();

Filters on IEnumerable property

Please visit How to deal with IEnumerable property blog for short and easy code. It will generates GraphQL query more faster (Please take a look in comments).

We provide other way to deal with IEnumerabe properties as below:

  • If T is the simple type (string, int, long, float, double, boolean, datetime), just use as normal property:
public class MyDocument{
  public IEnumerable<string> Ancestors{get;set;}
}

var query = queryBuilder
.ForType<MyDocument>()
  .Fields(x=>x.Name, x=>x.Url)
  .Where(x=> x.Ancestors.Eq("99d57529-61f2-47c0-80c0-f91eca6af1ac"))
.ToQuery()
.BuildQueries();
  • If T is a complex type, there are two options.

    1. Select IEnumerable property then the properties of T:

      public class Language{
        public string Name{get;set;}
        public string DisplayName{get;set;}
      }
      public class MyDocument{
        public IEnumerable<Language> ExistingLanguages{get;set;}
      }
      
      var query = queryBuilder
      .ForType<MyDocument>()
        .Fields(x=>x.Name, x=>x.Url)
        .Where(x=> x.ExistingLanguages, f=> f.Name.Eq("en"))
      .ToQuery()
      .BuildQueries();
      
    2. The most efficient way for dealing with IEnumberable<T> where T is a complex type is create an extension method for pretending property type IEnumberable<T> to be T. With that you can use all properties of type T when select, filter, or facet using a simple block of code. Ensure that the method name equals with property name.

      public static class CmsModelsExtension  
      {  
            ...  
           public static ContentLanguageModel ExistingLanguages(this Content myprop)  
           {  
               return null;  
           }  
      }  
      //now you want to select properties in ExistingLanguages field, just use method ExistingLanguages() instead of property ExistingLanguages :  
      query.Fields(x=> x.ExistingLanguages().Name, x.ExistingLanguages().DisplayName)  
      //filters  
      query.Where(x=> x.ExistingLanguages().Name.StartWith("e"))  
      //facets  
      query.Facet(x=> x.ExistingLanguages().Name.FacetLimit(10))
      

See Tool tips: Optimizely Graph Client Tool and how to leverage CMS data models to build query blog for more information.

📘

Note

  • If you have filter on properties of an IEnumerable<T> field, use the following example:
var query = queryBuilder
.ForType<MyDocument>()
  .Fields(x=>x.Name, x=>x.Url)
  .Where(x=> x.ExistingLanguages, f=> f.Name.Eq("en"))
.ToQuery()
.BuildQueries();
  • If you build many conditions on one field please create an instance of IFilterOperator. For example for filter language contains "en" but not "English" in DisplayName
var filterOperator = new StringFilterOperators().Contains("en").NotIn("English");
var query = queryBuilder
.ForType<MyDocument>()
  .Fields(x=>x.DisplayName, x=>x.Url)
  .Where(x=> x.ExistingLanguages, f=> f.DisplayName, filterOperator)
.ToQuery()
.BuildQueries();
  • Now combine both of them for more complex query. Lets assume you want to filter more than one conditions on both Name and DisplayName, you should create a logical filter instance then combine them before use .Where.
var operatorForName = new StringFilterOperators().Like("en").Boost(2);
var operatorForDisplayName = new StringFilterOperators().Eq("English").Boost(1);
var andFilter = BooleanFilter
.AndFilter<MyDocument>()
.And(x=>x.ExistingLanguages, f => f.Name, operatorForName)
.And(x=>x.ExistingLanguages, f => f.DisplayName, operatorForDisplayName);

var query = queryBuilder
.ForType<MyDocument>()
  .Fields(x=>x.Name, x=>x.Url)
  .Where(andFilter)
.ToQuery()
.BuildQueries();