HomeDev guideAPI ReferenceGraphQL
Dev guideUser GuideGitHubNuGetDev CommunitySubmit a ticketLog In
GitHubNuGetDev CommunitySubmit a ticket

Type query

How to use the type query builder and its important methods.

👍

Beta

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

Optimizely Graph contains types in the schema, and you must specify which type of data you want to retrieve. The TypeQueryBuilder class covers most of the important functionalities for querying documents of a type.

var query = queryBuilder
.ForType<MyDocument>() //start to build a type query
 .Total() //selected field
.ToQuery() //end of a type
.BuildQueries(); //combine all types into GraphQL query

The ForType<T> method will create an instance of TypeQueryBuilder for the typed query builder. The ToQuery method will mark that you have ended this typed query. These two methods are required for the beginning and ending of a typed query.

You can add the typed query to your query builder if you want to retrieve more types. An example for counting documents in MyDocument type and MyOtherType:

var query = queryBuilder
.ForType<MyDocument>() //required for beginning
  .Total()
.ToQuery() //required at the end of a typed query
.ForType<MyOtherType>()
  .Total()
.ToQuery()
.BuildQueries();

The BuildQueries method combines all typed queries and the full body of the request. It must be called before invoking the GetResultAsync() method.

Built-in functions for type query

Search()

Search is a built-in query for executing full-text search on a type. The parameter is your search string. The operation for this function is a Match operation to get the best matching result.

An example to get total items that matching for "shoes" in type MyDocument:

var query = queryBuilder
.ForType<MyDocument>()
.Search(“shoes”)
  .Total()
.ToQuery()
.BuildQueries();

Full-text search with more complex filtering

An overloading method, Search(IFilterOperator), is used on a type. The parameter, IFilterOperator, lets you pass one or more operations for filtering.

An example for counting MyDocument items containing "shoes" AND starting with "sneak":

var filterOperator = new StringFilterOperators()
.Contains(“shoes”)
.StartWith(“sneak”);

var query = queryBuilder
.ForType<MyDocument>()
.Search(filterOperator)
  .Total()
.ToQuery()
.BuildQueries();

FilterForVisitor

FilterForVisitor is a built-in filter for CMS that removes any pages that the current user does not have access to or is not currently published. The default implementation is to filter out documents that are not currently published.

An example that returns only published Article pages from CMS:

var query = queryBuilder
.ForType<ArticlePage>()
  .FilterForVisitor() // only published docs are returned
  .Field(x=>x.Name)
.ToQuery()
.BuildQueries();
var docs = await query.GetResultAsync<MyDocument>();

You can also implement your own filter from the IFilterForVisitor interface and then inject it into the service. The Optimizely Graph .NET Client gets all instances of IFilterForVisitor and then applies the filters.

For example, you can create a filter for visitors that returns only the pages that have the field SiteId set as "123-456-789":

[ServiceConfiguration(typeof(IFilterForVisitor))] //automatic injection by initialization module
public class RemoveSecretePageForVisitor : IFilterForVisitor
      public void FilterForVisitor<T>(TypeQueryBuilder<T> typeQueryBuilder)
      { 
          typeQueryBuilder.Where("SiteId", new StringFilterOperators().Eq("123-456-789"));
      }
 }

Then when you call the FilterForVisitor method, it will apply the filters in your RemoveSecretePageForVisitor class.

The other overloading method lets you inject your implementations of IFilterForVisitor into the FilterForVisitor method. It will only apply the passed filter arguments, not instances from service collection.

The following example applies myfilter1 and myfilter2 but does not apply RemoveSecretePageForVisitor, even if you have initialized this class before.

var myfilter1 = //create your instance of IFilterForVisitor
var myfilter2 = //create your other instance of IFilterForVisitor
  
var query = queryBuilder
.ForType<MyDocumentType>()
  .Field(x=>x.Name)
  .FilterForVisitor(myfilter1, myFilter2)
.ToQuery()
.BuildQueries();

Sub-type query (casting type)

Your query type may be an abstract type, sometimes, you want to get some properties on the concrete type that implemented abstract type. You can use the AsType<TSub>() method to select children types' fields.

The types returned are Content, but the fields in the response are Name and MetaTitle. If you want to get the NewsPage content, you should use the GetResultAsync and GetContent<TOriginalType,TDestinationType> methods to cast results from the Content type to the NewsPage type.

The following example gets Name from the Content abstract type and gets MetaTitle in the NewsPage type:

var query = queryBuilder
.ForType<Content>()
  .Search(“mycontent”)
  .Fields(x=>x.Name)
  .AsType<NewsPage>(x=>x.MetaTitle)
.ToQuery()
.BuildQueries();

var result = await query.GetResultAsync();
var newsPage = result.GetContent<Content,NewsPage>().Hits; // the result is an IEnumerable of NewsPage.