Projections
Introduction
While the API supports returning instances of the actual type that has been indexed (as long as it can be instantiated directly or by configuring the Client conventions), it often makes sense to return matching objects as instances of a different type, projecting them. As with LINQ, you do this with a Select method.
Projecting search results has several benefits. It lets you iterate over results that are more suitable for displaying search results and other types of listings. Also, because you are selecting a subset of the indexed data, only the required fields must be sent over the wire.
Example
Here 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 Titel = x.Title to Title = x.Title.ToLower(), the Title property would be retrieved from the search engine, then ToLower would execute 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. For more information, 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 EPiServer Find.NET client API's Select method is not as powerful as the in-memory LINQ version. But, compared to most other LINQ providers, the method is quite 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.
Further examples
In general, the Select method works as expected if you are used to working with the LINQ equivalent and remember the limitation of not being able to project from complex objects. Below are more examples of the method.
Projecting to anonymous type
var result = client.Search<BlogPost>()
.Select(x => new {
x.Title,
AuthorName = x.Author.Name })
.GetResult();
Projecting multiple fields to a single field
var result = client.Search<BlogPost>()
.Select(x => new {
x.Title,
AuthorInfo = x.Author.Name + " id: " + x.Author.Id })
.GetResult();
Projecting from a complex type to a simple type
var result = client.Search<BlogPost>()
.Select(x => x.Author.Id)
.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 to which you are projecting search results.
Last updated: Sep 21, 2015