November Happy Hour will be moved to Thursday December 5th.

Loading...
Area: Optimizely Search & Navigation
ARCHIVED This content is retired and no longer maintained. See the latest version here.

Recommended reading 

This topic explains the Unified Search concept in Episerver Find. Unified Search lets you index and query objects of existing classes without having to map them to an intermediate type that is put into the index.  

Components

Unified Search has four parts:
  • A common interface, ISearchContent, for declaring properties to use when building search (not querying) functionality.
  • An object that maintains a configurable list of types to be searched when searching for ISearchContent. Also, optionally, rules for filtering and projecting those types when searching IUnifiedSearchRegistry, which is exposed by the IClient.Conventions.UnfiedSearchRegistry property.
  • Classes for results returned when searching for ISearchContentUnifiedSearchResults, which contain a number of UnifiedSearchHit.
  • Special methods for building and executing search queries: UnifiedSearch(), UnifiedSearchFor(), and an overloaded GetResult() method.

ISearchContent

The ISearchContent interface resides in the EPiServer.Find.UnifiedSearch namespace and is the least common denominator. The interface declares several properties for which you may search, all of whose names begin with Search. Classes registered in Unified search do not have to implement ISearchContent. By having a property or extension method with the same name and type as a property in the interface, the property is treated as if it were received from the interface.

  • SearchTitle
  • SearchSummary
  • SearchText
  • SearchHitUrl
  • SearchTypeName
  • SearchHitTypeName
  • SearchSection
  • SearchSubsection
  • SearchAuthors
  • SearchGeoLocation
  • SearchPublishDate
  • SearchUpdateDate
  • SearchAttachment
  • SearchCategories
  • SearchFilename
  • SearchFileExtension
  • SearchMetaData
C#
public class MySearchableClass
{
    public string Heading { get; set; }
    public string Body { get; set; }
    public string Url { get; set; }

    public virtual string SearchTitle { get { return Heading; } }
    public virtual string SearchSummary { get { return Body; } }
    public virtual string SearchText { get { return String.Format(CultureInfo.InvariantCulture, "{0} {1} {2}", Heading, Body, Url); } }
    public virtual string SearchHitUrl { get { return Url; } }
    public virtual string SearchSection { get { return GetType().Name; } }
}

IUnifiedSearchRegistry

IUnifiedSearchRegistry, also residing in EPiServer.Find.UnifiedSearch, exposes methods for building and configuring a list of types that should be included when searching for ISearchContent. In addition to methods for adding (the Add method) and listing types (the List method), IUnifiedSearchRegistry declares methods that let you add rules to filter specific types when searching and projecting found documents to the common hit type (UnifiedSearchHit).

C#
SearchClient.Instance.Conventions.UnifiedSearchRegistry<br/>
.Add<MySearchableClass>();

UnifiedSearchResults and UnifiedSearchHit

While ISearchContent provides a decent common denominator for fields in which to search, it is not useful for getting back instances of it as the result of a search query. For instance, while you may want to search an indexed object's full text, you typically only want back a small text snippet to display in search results. Also, it is technically problematic to get instances of ISearchContent back from the search engine, since the matched object does not actually implement that interface, or at least it does not have to.

Therefore, when searching for ISearchContent and invoking the GetResult method, you do not get back instances of ISearchContent. Instead, you get an instance of the UnifiedSearchResults class, which contains several UnifiedSearchHit objects. A UnifiedSearchHit object contains properties that you would typically want to display for each search result, such as Title, URL and excerpt (text snippet). The UnifiedSearchHit object has additional properties, such as PublishDate, ImageUri, Section, FileExtension and TypeName.

Methods for building and executing queries

To search for ISearchContent, use the regular Search method, client.Search(). When doing so, you determine which fields to search when building free text search. Since ISearchContent is a special type that the .NET API knows about, two methods enable you to add sensible defaults: UnifiedSearch() and UnifiedSearchFor().

The Unified Search concept also provides a GetResult method. Because it has the same name as the regular method for executing search queries, you do not have to do anything special to use the GetResult method. Because it has a more specific generic-type constraint than other GetResult methods, the compiler uses it.

Note: The GetResult method modifies search queries by searching for objects that implement ISearchContent and also for all types added to the UnifiedSearchRegistry. The GetResult method also adds a projection from ISearchContent to UnifiedSearchHit with sensible defaults, along with any type-specific projections added to the UnifiedSearchRegistry. Finally, before executing a search query (such as the GetResult method), Unified Search adds type-specific filters that were added to the UnifiedSearchRegistry.

When you invoke GetResult, the search query searches types that may not have implemented ISearchContent. But since you (hopefully) specified to only search in, or filter on, a number of fields declared by ISearchContent, the search only considers fields with those names, even if the objects do not implement ISearchContent. The GetResult method has an overload that requires an argument of type HitSpecification. This argument lets you control the length of the excerpt, whether to highlight titles and excerpts, and so forth.

C#
SearchClient.Instance.UnifiedSearchFor(searchQuery).GetResult()

Customize default projections

You can customize the projection of unified search results in several ways. The UnifiedSearchRegistry supports these options:

  • ProjectTitleFrom
  • ProjectTypeNameFrom
  • ProjectUrlFrom
  • ProjectImageUriFrom
  • UseHitType
  • ProjectHighlightedExcerptUsing
  • AlwaysApplyFilter
  • PublicSearchFilter
  • CustomizeProjection

ProjectTitleFrom

To register the Title for a specific document type:

C#
client.Conventions.UnifiedSearchRegistry
                .ForInstanceOf<MySearchableClass>()
                .ProjectTitleFrom(x => x.MyTitleProperty);

ProjectTypeNameFrom

To register the TypeName for a specific document type:

C#
client.Conventions.UnifiedSearchRegistry
                .ForInstanceOf<MySearchableClass>()
                .ProjectTypeNameFrom(x => x.MyTypeNameProperty);

ProjectUrlFrom

To register the Url for a specific document type:

C#
client.Conventions.UnifiedSearchRegistry
                .ForInstanceOf<MySearchableClass>()
                .ProjectUrlFrom(x => x.MyUrlProperty);

ProjectImageUriFrom

To register the ImageUri for a specific document type:

C#
client.Conventions.UnifiedSearchRegistry
                .ForInstanceOf<MySearchableClass>()
                .ProjectImageUriFrom(x => x.MyImageUriProperty);

UseHitType

To register the type of the result item for a specific document type:

C#
client.Conventions.UnifiedSearchRegistry
                .ForInstanceOf<MySearchableClass>()
                .UseHitType<MySearchableHitClass>();

ProjectHighlightedExcerptUsing

To register the highlighted excerpt for a specific document type:

C#
client.Conventions.UnifiedSearchRegistry
                .ForInstanceOf<MySearchableClass>()
                .ProjectHighlightedExcerptUsing<ISearchContent>(spec =>
                            x => x.MyHighlightedProperty.AsHighlighted(
                                new HighlightSpec { FragmentSize = spec.ExcerptLength, NumberOfFragments = 1 }));

AlwaysApplyFilter

To register a filter always applied for UnifiedSearch:

C#
client.Conventions.UnifiedSearchRegistry
                .ForInstanceOf<MySearchableClass>()
                .AlwaysApplyFilter(f => f.BuildFilter<MyType>().And(x => !x.MyProperty.Match("Something")));

PublicSearchFilter

To register a filter always applied for public UnifiedSearch:

C#
client.Conventions.UnifiedSearchRegistry
                .ForInstanceOf<MySearchableClass>()
                .PublicSearchFilter(f => f.BuildFilter<MySearchableClass>().And(x => !x.MyProperty.Match("Something")));

CustomizeProjection

If the other projection options are inadequate, the CustomizeProjection extension provides full access to the HitProjectionBuilder.

Highlighting and encoding unified search results

For unified search results, HTML encoding is enabled by default for "title" and "excerpt" fields. The text is encoded before adding the HTML tags that surround highlighted content.

Example

var hitSpec = new HitSpecification
{
HighlightExcerpt = true

// HighlightTitle = false by default,
// EncodeExcerpt = true by default,
// EncodeTitle = true by default

};

var result = searchClient.UnifiedSearchFor("apples").GetResult(hitSpec);

// result.Hits.First().Document.Excerpt contains I like <em>apples</em>.

Disabling HTML encoding

To disable HTML encoding, set the EncodeTitle and EncodeExcerpt properties of the HitSpecification to "false." If you do, ensure that the implementation handles the encoding of results, to ensure normal rendering and avoid script injections. You may also implement custom highlighting.

Example

var hitSpec = new HitSpecification
{
HighlightExcerpt = true,
EncodeTitle = false,
EncodeExcerpt = false
};

var result = searchClient.UnifiedSearchFor("apples").GetResult(hitSpec);
// result.Hits.First().Document.Excerpt contains I like <em>apples</em>.

 

Do you find this information helpful? Please log in to provide feedback.

Last updated: Nov 16, 2015

Recommended reading