Enabling and disabling result type projection

Abstract

The Content Search LINQ API uses the fl parameter of the Solr Query API to specify a list of fields that Solr returns in a search result.

Note

This feature (called result type projection) is enabled by default, but you can disable it.

When you use this parameter, query performance improves in several ways:

  • The resources Solr uses to provide the search result are reduced.

  • The resources Sitecore uses to process the search result are reduced.

  • The time it takes to execute queries is improved.

For example, if you have the following code:

public class SimpleResultItem
{
 [IndexField("_name")]
 public string Name { get; set; }

 [IndexField("_uniqueid")]
 public virtual ItemUri Uri { get; set; }

 [IndexField("_template")]
 public virtual ID TemplateId { get; set; }
}

and you execute the following LINQ query:

SimpleResultItem[] result = context.GetQueryable<SimpleResultItem>()
       .Where(i => i.Name == "home").ToArray();

then you can see in the search log that it translates to the following Solr query:

q=_name:(home) AND _val_:__boost&fl=_name,_template,_uniqueid,_datasource&…

The list of fields to retrieve was resolved based on the properties available in the result type. This is result type projection. The _uniqueid and _datasource fields are required for system use so they always appear in the list.

This following example is a query that uses the Select(…) method with anonymous type:

var result = context.GetQueryable<SimpleResultItem>()
        .Where(i => i.Name == "home")
        .Select(i => new {i.Name}).ToArray();

It only retrieves three fields from Solr:

q=_name:(home) AND _val_:__boost&fl=_name,_uniqueid,_datasource&…

You can actually use separate types for searching and retrieving results. This is useful because it allows you to have a rich set of properties available for search and at the same time get lean search results. In the following example, the query uses the default SearchResultItem type for searching and SimpleResultItem for retrieving the result:

SimpleResultItem[] result = context.GetQueryable<SearchResultItem>()
 .Where(i => i.Content == "sitecore")
 .Filter(i => i.Paths.Contains(contentItemId))
 .Cast<SimpleResultItem>().ToArray();

This translates to the following:

q=_content:(sitecore) AND val_:__boost&fq=_path:(0de95ae441ab4d019eb067441b7c2450)&fl=_name,_template,_uniqueid,_datasource&…

Even though the SearchResultItem type has more than 20 properties, the provider requests only the four fields that are sufficient to populate objects of the SimpleResultItem type.

Disabling result type projection

Result type projection is enabled by default. You can, however, disable it to keep backwards compatibility with previous Sitecore versions. The type projection is disabled if the result type meets one of these criteria:

  • The type has an indexer

  • The type has properties marked with the CollapsedIndexFieldAttribute attribute

  • The number of fields in the type reaches the limit defined in the "ContentSearch.Solr.MaxNumberOfFieldsToProject" setting of your Sitecore configuration

You can forcibly enable or disable projection at query level if you pass the ResultTypeProjectionExecutionContext execution context to the GetQueryable method with the appropriate parameter:

var disableProjection = ResultTypeProjectionExecutionContext.Switch(isEnable: false);
         
SimpleResultItem[] result = context.GetQueryable<SimpleResultItem>(disableProjection)
 .Where(i => i.Name == "home").ToArray();

The Solr query does not contain the fl parameter:

q=_name:(home) AND _val_:__boost&fq=_indexname:(sitecore_master_index)&…