Dev guideRecipesAPI ReferenceChangelog
Dev guideRecipesUser GuidesNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev guide

Where filter

Describes filtering on a document using the Where method.

📘

Note

Optimizely Graph .NET Source SDK is optimized for CMS 12. Learn more about the C# SDK for CMS 13.

Use the Where method to apply Where filter conditions to a 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();

IFilterOperator has four implementations:

  • 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 – The filter operators for the DateTime field type.
  • StringFilterOperators – The filter operators for the String field type.

Filter expression

Optimizely Graph .NET Client supports built-in functions and Boolean logical operators in filter queries. The syntax is similar to the Search & Navigation (formerly FIND) client.

The following example filters on an ArticlePage to return 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

Boolean filters combine multiple conditions into a single Where clause so you can express AND, OR, and NOT logic without nesting separate filter calls. Use a Boolean filter when the condition you need cannot be expressed as a single field comparison. The Optimizely Graph .NET Client provides three Boolean filter classes:

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

Create one of the preceding classes using the BooleanFilter class. The static methods AndFilter(), OrFilter(), and NotFilter() create AndFilter, OrFilter, and NotFilter instances.

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

Use the basic logical operators & (AND), | (OR), and ! (NOT) to create 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 complex filter queries, use a filter-operator variable.

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 SDK implicitly applies AND logic.

For example, to 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, build the same functionality with one of the following approaches:

  • 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();
  • 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.Property1.NotIn(4,5,6)) // use AND logic conditionally
.ToQuery()
.BuildQueries();

Filters on IEnumerable\<T> property

For a concise pattern, see the Optimizely Graph Client: dealing with CMS data models for Query Builder blog. The pattern described in the blog generates GraphQL queries with fewer round trips; see the blog comments for additional discussion.

The SDK provides the following options for working with IEnumerable<T> properties:

  • If T is a simple type (string, int, long, float, double, bool, or DateTime), use it as you would a 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.

    • 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();
    • The most efficient way to filter on an IEnumerable<T> where T is a complex type is to add an extension method that returns T from the parent type. After you add the extension method, you can use the properties of T directly when selecting, filtering, or faceting. The extension method name must match the 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();
  • To build many conditions on one field, create an instance of IFilterOperator. For example, to filter language values that contain "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. 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();