Coveo for Sitecore 5 is now available!

Retrieving Metadata in LINQ Query Results

Coveo for Sitecore 4.1 (November 2018)

When implementing a search interface, one feature that is present almost every time is the excerpt. The excerpt consists of the fragment of the search result that is the most pertinent regarding the current search query. In this example, a user performs the query foo and the web page named foo bar appears in the search results. Supposing that the foo bar page is quite long, you would not want to display the whole content in the search page. Instead, you would want to present a small and relevant part of the content to help the user choose if this result is the result they were looking for. That is exactly the purpose of this excerpt.

This article explains how to retrieve dynamic result metadata such as excerpt, first sentences, summary, and more. Coveo also provides the necessary highlighting information to highlight the searched terms in the search results for these dynamic metadata fields.

Retrieving Dynamic Metadata and Highlights

Due to efficiency reasons, not all the dynamic metadata fields are filled automatically. By default, the following fields are filled when querying instances of type Sitecore.ContentSearch.SearchTypes.SearchResultItem.

  • coveo_excerpt: Contains the excerpt text.
  • coveo_excerpt_highlights: Contains the list of highlights to apply on the excerpt text.
  • coveo_printable_uri: Contains the printable URI text.
  • coveo_printable_uri_highlights: Contains the list of highlights to apply on the printable URI text.
  • coveo_title: Contains the result title as it appears in the Coveo search index.
  • coveo_title_highlights: Contains the list of highlights to apply on the title text.

The code sample below shows how to perform a LINQ query and retrieve the excerpt and highlights.

ISearchIndex index = ContentSearchManager.GetIndex("Coveo_web_index");
using (var context = index.CreateSearchContext()) {
    // We are simply searching for the term "foo" in the "Coveo_web_index".
    var queryable = context.GetQueryable<SearchResultItem>().CoveoWhere("foo");
 
    // Let's retrieve the excerpt with highlights for the first result
    SearchResultItem firstResult = queryable.FirstOrDefault();
    if (firstResult != null) {
        string excerpt = firstResult["coveo_excerpt"];
        IEnumerable<Highlight> excerptHighlights = firstResult[(ObjectIndexerKey) "coveo_excerpt_highlights"] as IEnumerable<Highlight>;
 
        // Calling the "Highlight" method surrounds the lit areas with span elements. e.g., This is the <span class="highlight">text</span> to highlight.
        string excerptWithHighlight = Coveo.UI.WebUtilities.Highlight(excerpt, excerptHighlights);
    }
}

The Sitecore.ContentSearch.SearchTypes.SearchResultItem contains two different indexers. The most commonly used is the String indexer that takes a field name as a System.String and returns its value as a System.String.

string this[string key]

Unfortunately, this first indexer cannot return complex types without doing some custom work. This is why Sitecore added another indexer that can return a field value in its native type.

object this[Sitecore.ContentSearch.SearchTypes.ObjectIndexerKey key]

You can cast the field name into an ObjectIndexerKey instance and use it as in the example below.

SearchResultItem result = GetSomeResult();
object fieldValue = result[(ObjectIndexerKey) "field name"];

As shown in the example above, the Highlight method can easily use the highlight information to surround specific parts of the excerpt with the highlighting HTML elements. A second overload exists where you are able to specify which opening and closing elements to use.

public static string Highlight(string p_Text,
                               IEnumerable<Highlight> p_Highlights)
 
public static string Highlight(string p_Text,
                               IEnumerable<Highlight> p_Highlights,
                               string p_HighlightOpeningElement,
                               string p_HighlightClosingElement)

The length of the excerpt is not a fixed value. It can be configured with the ExcerptLength setting in the Coveo.SearchProvider.Custom.config file. The element is located under /configuration/sitecore/coveo/defaultIndexConfiguration/queryConfiguration/ExcerptLength.

<ExcerptLength>200</ExcerptLength>

Remember that, to avoid upgrading issues or unexpected bugs, you should perform your modifications in the Coveo.SearchProvider.Custom.config file instead of the Coveo.SearchProvider.config file.

Retrieving Additional Dynamic Metadata Fields

Two other fields are available. However, because they are rarely used, they are not filled by default.

  • coveo_first_sentences: Contains the first sentences of the item in which the search terms appear.
  • coveo_first_sentences_highlights: Contains the list of highlights to apply on the first sentences text.
  • coveo_summary: Contains the item summary.
  • coveo_summary_highlights: Contains the list of highlights to apply on the summary text.

To fill these fields, an integrator must set the RetrieveFirstSentences and SummaryLength settings in the Coveo.SearchProvider.Custom.config file. The elements are located under /configuration/sitecore/coveo/defaultIndexConfiguration/queryConfiguration/ExcerptLength.

<RetrieveFirstSentences>true</RetrieveFirstSentences>
<SummaryLength>300</SummaryLength>

The length of the first sentences field is based on the ExcerptLength setting.

Remember that, to avoid upgrading issues or unexpected bugs, you should perform your modifications in the Coveo.SearchProvider.Custom.config file instead of the Coveo.SearchProvider.config file.

Customizing the Results Mapping

When performing a search query through LINQ, the information follows these steps:

  1. When the collection is iterated, a search query is performed on the search index.
  2. The search results are returned using a generic type.
  3. The search results are mapped to the target collection type.
  4. The results are available in the client code.

It is possible to customize the way the search results are mapped, depending mostly on the collection type, which is specific to an integrator implementation. You can use the coveoMapLinqQueryResult pipeline to set specific values to the mapped result when a LINQ query is performed. The pipeline is invoked for every search result, and provides the generic search result and the target search result. You can then set the properties of the target search result to suit your needs. See Understanding the Indexing and Search Pipelines.