HomeDev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideGitHubNuGetDev CommunitySubmit a ticketLog In
GitHubNuGetDev CommunitySubmit a ticket

Projections

Describes how to work with projections of search results in Optimizely Search & Navigation. Projecting search results allows you to refine search results for display, and has performance benefits.

Projecting search results lets you iterate over more suitable results for displaying search results and other listings. Also, because you select a subset of the indexed data, only the required fields must be sent over the wire.

While the API supports returning instances of the actual type that is indexed (as long as it can be instantiated directly or by configuring the Client conventions), you should return matching objects as instances of a different type, projecting them. As with LINQ, you do this with a Select method.

This is a projection from a type named BlogPost to a type named SearchResult.

var result = client.Search<BlogPost>()
  .Select(x => new SearchResult
    { 
      Title = x.Title, 
      Author = x.Author.Name
    })
  .GetResult();

Special methods

In general, if you invoke a method in a select expression, the method is invoked on the target object after fetching it from the search engine. In other words, if you changed the above example from Title = x.Title to Title = x.Title.ToLower(), the Title property is retrieved from the search engine, then ToLower executes on the client.

However, some extension methods get special treatment when parsed in a select expression. One is the AsHighlighted method. When using this, you can project fragments from the source text into the result object. See Highlighting.

Another such method is AsCropped. This lets you retrieve only the beginning of a longer text field. AsCropped requires a single integer parameter, which controls the maximum length of the returned text. Unlike the SubString method, no exception is thrown if the actual text is shorter than the requested maximum length. Here is a sample usage.

var result = client.Search<BlogPost>()
  .Select(x => new SearchResult
    { 
      Title = x.Title.AsCropped(50), 
      Author = x.Author.Name
    })
  .GetResult();

AsCropped tries to crop text to the specified maximum length without separating words.

📘

Note

Because the method uses a script on the search engine side, the execution is slower than projections that do not use it.

Limitations

The Optimizely Search & Navigation .NET client API's Select method is less powerful than the in-memory LINQ version. Compared to most other LINQ providers, the method is powerful.

The Select method's primary limitation is that it does not support projecting from complex types, except for enumerables of non-complex types. In other words, in the example above, you could not project the full Author object. However, you could project individual fields from the Author object to a complex object.

Another limitation is that the Select method can not project user-defined functions or delegates. When you use a user-defined function, it could request and load the entire object, including the binary attachment fields and nested objects. Avoid using user-defined functions or delegates. Instead, explicitly declare the projection in the select expression.

Examples

In general, the Select method works as expected if you are used to working with the LINQ equivalent, but remember the limitation of being unable to project from complex objects. Below are more examples of the method.

var result = client.Search<BlogPost>()
  .Select(x => new
    { 
      x.Title, 
      AuthorName = x.Author.Name
    })
  .GetResult();
var result = client.Search<BlogPost>()
  .Select(x => new
    { 
      x.Title, 
      AuthorInfo = x.Author.Name + " id: " + x.Author.Id
    })
  .GetResult();
var result = client.Search<BlogPost>()
  .Select(x => x.Author.Id)
  .GetResult();

And avoid doing something like this.

var result = client.Search<BlogPost>()
  .Select(x => new
    { 
      x.Title, 
      Parent = GetParent(x) // This is the problematic row.
    })
  .GetResult();

Select and the fluent API

In general, call the Select method after calling searching and filtering methods. Those methods depend on the type you are searching for rather than the type you are projecting search results to.