Building a search interface for local indexes

To allow users to search your website using locally stored indexes, you need to build pages with a search interface. Use the API from the CMS.Search namespace (provided as part of the Kentico.Xperience.Libraries NuGet package).

  1. Prepare a SearchParameters object with the required search inputs and parameters.

  2. Call the SearchHelper.Search method.

    Example
    
    
    
                 // Prepares variables required to perform the search operation
                 IEnumerable<string> searchIndexes = new List<string> { "ProductIndex", "ArticleIndex" };
                 int pageNumber = 1;
                 int pageSize = 10;
                 UserInfo searchUser = MembershipContext.AuthenticatedUser;
                 string cultureCode = "en-us";
                 /* Indicates whether the search service uses site default language version of pages as a replacement
                 for pages that are not translated into the language specified by 'cultureCode' */
                 bool combineWithDefaultCulture = true;
    
                 // Prepares a 'SearchParameters' object to search through indexes of the 'Pages' type
                 SearchParameters searchParameters = SearchParameters.PrepareForPages("search query", searchIndexes, pageNumber, pageSize, searchUser, cultureCode, combineWithDefaultCulture);
    
                 // Searches the specified indexes
                 SearchResult searchResult = SearchHelper.Search(searchParameters);
    
    
    
     

The Search method returns a SearchResult object representing the set of results. The result’s Items property contains a collection of SearchResultItem objects, representing individual search results.

Every SearchResultItem provides the following data:

  • Properties corresponding to general search result fields (such as the title, image or content extract), which contain data based on the field mapping of the indexed object type.
  • Properties related to the relevance score and positioning of the result item for the given search.
  • The Data property, which you can use to access any object-specific values of the searched items.

The Dataproperty is of an abstract BaseInfo type, and its run-time type depends on the searched Xperience object. For example:

  • If the search indexes pages, the run-time type of a search result item’s Dataproperty is of the TreeNode class. If you generated classes for your page types, the run-time type is of the generated class.
  • If the search indexes pages representing products, the run-time type of a search result item’s Data property is of the SKUTreeNode class.
  • If the search indexes users, the run-time type of a search result item’s Dataproperty is of the UserInfo class.

Preparing the SearchParameters object

Search is performed by passing a SearchParameters object to the SearchHelper.Search method. The object contains all information required by the system to complete the search operation. Since the SearchParameters object is complex and requires a large amount of contextual information, the system provides the SearchParameters.PrepareForPages method to facilitate its creation. The method takes the following parameters:

Parameter

Type

Description

searchText

—OR—

searchPattern

string

—OR—

SearchPattern

The query text. See Smart search syntax for a reference of supported syntax.

You can specify the search query using query text or a SearchPattern object. The object consists of the following:

  • SearchText – the search query to search for in the given indexes.
  • SupportedSearchSyntax – an object of the SearchOptionsEnum type that sets the level of supported Lucene syntax for the search query.

SearchOptionsEnum allows the following options:

  • NoneSearch – the search does not recognize any Lucene query syntax. The system processes all text entered by users as a part of the search expression.
  • BasicSearch – the search recognizes all query syntax, except for field search.
  • FullSearch – the search processes all search query syntax, including field search.

searchIndexNames

IEnumerable<string>

Code names of the indexes to search.

pageNumber

int

The page number of paginated results to retrieve starting from 1.

pageSize

int

The number of results on each page.

user

IUserInfo

The user for whom to filter the search results. For example, filters out pages the user is not authorized to view.

cultureName

string

Culture code of the culture to search in. If null, searches in all cultures.

combineWithDefaultCulture

bool

Indicates whether the search service uses site default language version of pages as a replacement for pages that are not translated into the language specified by cultureName.

Number of processed search results

Every search request has a maximum number of processed and returned search results. The purpose of the limit is to avoid processing large numbers of results with low relevance. The limit is determined by the NumberOfProcessedResults property of the SearchParameters object that you use to perform the search.

By default, the SearchParameters.PrepareForPages method sets the NumberOfProcessedResults property to 100. If you use large search indexes that regularly produce more results, you can either set a higher value for the property before calling SearchHelper.Search, or implement search filters to help narrow down the search.

Searching according to page permissions

To filter out search results for pages that users are not allowed to access, set the CheckPermissions property to true for the used SearchParameters object. The search results then contain pages according to the read permissions of individual users.

Example – Building a search interface

The following search example uses an index that covers pages (TreeNode objects) and products (SKUTreeNode objects). The example does not use pagination when displaying search result items.

  1. Open your live site (MVC) project in Visual Studio.

  2. Create a new model class for working with search queries and search result items.

    
    
    
     using System.Collections.Generic;
     using CMS.Search;
    
    
     
    
    
    
         public class SearchResultModel
         {
             public string Query { get; set; }
    
             public IEnumerable<SearchResultItem> Items { get; set; }
         }
    
    
    
     
  3. Create a controller with an action that searches and provides search results.

    
    
    
     using System;
     using System.Collections.Generic;
     using System.Web.Mvc;
    
     using CMS.Membership;
     using CMS.Search;
    
    
    
     
    
    
    
             // Adds the smart search indexes that will be used to perform searches
             public static readonly string[] searchIndexes = new string[] { "MVCSite.Index" };
             // Sets the limit of items per page of search results
             private const int PAGE_SIZE = 10;
    
             /// <summary>
             /// Performs a search and displays its result.
             /// </summary>
             [ValidateInput(false)]
             public ActionResult SearchIndex(string searchText)
             {
                 // Displays the search page without any search results if the query is empty
                 if (String.IsNullOrWhiteSpace(searchText))
                 {
                     // Creates a model representing empty search results
                     SearchResultModel emptyModel = new SearchResultModel
                     {
                         Items = new List<SearchResultItem>(),
                         Query = String.Empty
                     };
    
                     return View(emptyModel);
                 }
    
                 // Searches the specified index and gets the matching results
                 SearchParameters searchParameters = SearchParameters.PrepareForPages(searchText, searchIndexes, 1, PAGE_SIZE, MembershipContext.AuthenticatedUser, "en-us", true);
                 SearchResult searchResult = SearchHelper.Search(searchParameters);
    
                 // Creates a model with the search result items
                 SearchResultModel model = new SearchResultModel
                 {
                     Items = searchResult.Items,
                     Query = searchText
                 };            
    
                 return View(model);
             }
    
    
    
     
  4. Add a search input field to one of your site’s views. For example:

    
    
    
     @using (Html.BeginForm("SearchIndex", "Search", FormMethod.Get))
     {
         <input type="text" name="searchtext" placeholder="Search..." maxlength="1000">
         <input type="submit" value="Search">
     }
    
    
    
     
  5. Create a view that displays the search result items provided by your search controller. For example:

    
    
    
     @model SearchResultModel
    
     @using CMS.Search;
    
     @if (!Model.Items.Any())
     {
         if (!String.IsNullOrWhiteSpace(Model.Query))
         {
             <h3>No results found for "@Model.Query"</h3>
         }
     }
     else
     {
         <h3>Results for "@Model.Query"</h3>
         foreach (SearchResultItem item in Model.Items)
         {
         <div>
             <strong>@item.Title</strong>
         </div>
         <div>
             @Html.Kentico().ResolveUrls(item.Content)
         </div>
         }
     }
    
    
    
     

Your visitors can now search on your website through the created search field. The system searches through the specified indexes and displays the results.