THIS IS ARCHIVED DOCUMENTATION

LINQ QueryResults Example: Add a Sorting Section

Coveo for Sitecore (July 2016) Coveo for Sitecore 4.1 (November 2018)

This section contains information on how to add a sort section to your search page.

It uses the basic search page presented in LINQ QueryResults Example - Create a Basic Search Page.

Note that this is one of the many possible solutions. Feel free to experiment and implement your own solution more adapted for your use case.

Define the SortTypes You Want to Use

Add a new class that contains all the types of sort you want to handle in your search page.

LinqBasedPageExample_5.aspx.cs

public static class SortTypes {
    public const string Date = "date";
    public const string Relevancy = "relevancy";
}

Add the Sorting to the Model

This adds the information needed to sort the query. Since you most probably want the user to get the most recent results when selecting the Date sorting, set SortDescending to true by default.

LinqBasedPageExample_5.aspx.cs

public class SearchModel {
    public string Query { get; set; }
    public string SortType { get; set; }
    public bool SortDescending { get; set; }
    
    public SearchModel() {
        Query = "";
        SortType = SortTypes.Relevancy;
        SortDescending = true;
    }
}

Add the field you want to sort in your SearchResult. This example uses the Updated field.

The field you want to sort must be tagged as Sortable to be sorted.

LinqBasedPageExample_5.aspx.cs

public class SearchResult {
    public DateTime Updated { get; set; }
    public DateTime Date { get; set; }
    public string Title { get; set; }
    public string PrintableURI { get; set; }
}

Add Sorting to the Query

Since LINQ queries can’t handle OrderByDescending using a Boolean value, it’s required to split the expression in two: one using OrderBy, and the other using OrderByDescending, depending on the user choice.

Relevancy sort is never sorted as descending (from less relevant to more relevant), so you can return the query without sorting it.

To simplify the query code, add this new extension method that wraps the sorting logic in your server-side file:

LinqBasedPageExample_5.aspx.cs

public static class QueryableSearchResultsExtensions {
    public static IQueryable<SearchResult> SortBy(this IQueryable<SearchResult> query,
                                                  string sortType,
                                                  bool isDescending) {
        switch(sortType){
            case SortTypes.Date:
                return isDescending ? query.OrderByDescending(item => item.Updated)
                                    : query.OrderBy(item => item.Updated);
            case SortTypes.Relevancy:
                return query;
            default:
                throw new NotSupportedException("This sort type is not supported.");
        }
    }
}

You can now use this extension in your query execution.

LinqBasedPageExample_5.aspx.cs

private QueryResults<SearchResult> ExecuteQuery(SearchModel model) {
    QueryResults<SearchResult> results;
    ISearchIndex index = ContentSearchManager.GetIndex("Coveo_web_index");
    using (var context = index.CreateSearchContext()) {
          IQueryable<SearchResult> query = context.GetQueryable<SearchResult>()
                                                  .CoveoOr(model.Query)
                                                  .SortBy(model.SortType, model.SortDescending);
          results = query.GetCoveoQueryResults();
    }
    return results;
}

Add the Sorting Section to the Interface

To add a sorting section in your interface, add the following section to your page, after your query box. This section contains every sort types you want to handle, and whether to sort the results in ascending or descending order.

Selecting descending doesn’t have any effect when Relevancy is selected.

LinqBasedPageExample_5.aspx

<div class="sortSection">
    <asp:DropDownList ID="SortList" AppendDataBoundItems="true" AutoPostBack="true" runat="server">
        <asp:ListItem Text="Relevancy" Value="relevancy"></asp:ListItem>
        <asp:ListItem Text="Date" Value="date"></asp:ListItem>
    </asp:DropDownList>
    <asp:Checkbox ID="SortDescending" Text="Descending" Checked="true" AutoPostBack="true" runat="server" />
</div>

It’s now possible to bind the SortList to the model:

LinqBasedPageExample_5.aspx.cs

private void MapControlsToModel(SearchModel model) {
    model.Query = Querybox.Text;
    model.SortDescending = SortDescending.Checked;
    model.SortType = SortList.SelectedValue;
}

Result

When sorting with the Date field, you should get a page similar to this:

When clicking Descending to sort in the ascending direction, you should get a page similar to this:

Client-Side Code

Your client-side code should now look like this:

LinqBasedPageExample_5.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="LinqBasedPageExample.aspx.cs" Inherits="Tutorial.LinqBasedPageExample" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>LINQ-based Page Example</title>
</head>
<body>
    <form id="pageForm" runat="server">
        <div class="searchSection">
            <div class="searchSection">
                <asp:Literal Text="Query: " runat="server" />
                <asp:TextBox ID="Querybox" runat="server" />
            </div>
            <div class="sortSection">
                <asp:DropDownList ID="SortList" AppendDataBoundItems="true" AutoPostBack="true" runat="server">
                    <asp:ListItem Text="Relevancy" Value="relevancy"></asp:ListItem>
                    <asp:ListItem Text="Date" Value="date"></asp:ListItem>
                </asp:DropDownList>
                <asp:Checkbox ID="SortDescending" Text="Descending" Checked="true" AutoPostBack="true" runat="server" />
            </div>
            <asp:Button type="submit" Text="Run Query" runat="server" />
        </div>
        <div ID="ResultsSection" class="resultsSection" runat="server">
            <asp:GridView ID="LSTResults" AutoGenerateColumns="true" runat="server" />
        </div>
    </form>
</body>
</html>

Server-Side Code

Your server-side code should now look like this:

LinqBasedPageExample_5.aspx.cs

namespace Tutorial {
    using System;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using Coveo.Framework.SearchService;
    using Coveo.SearchProvider.Linq;
    using Coveo.SearchProvider.LinqBase;
    using Sitecore.ContentSearch;
    using Sitecore.ContentSearch.Linq;
    using Sitecore.ContentSearch.SearchTypes;
    public partial class LinqBasedPageExample : Page {
        protected void Page_Load(object sender, EventArgs e) {
            SearchModel searchModel = new SearchModel();
            if (Page.IsPostBack) {
                MapControlsToModel(searchModel);
                Render(searchModel);
            }
        }
        private void Render(SearchModel model) {
            if(!String.IsNullOrEmpty(model.Query)) {
                ClearResults();
                QueryResults<SearchResult> results = ExecuteQuery(model);
                if(results.TotalCount != 0) {
                    RenderWithResults(model, results);
                }else{
                    RenderWithoutResults(model, results);
                }
                RenderCommon(model, results);
            }
        }
        private void ClearResults() {
            LSTResults.DataSource = "";
            LSTResults.DataBind();
        }
        private void RenderWithResults(SearchModel model,
                                       QueryResults<SearchResult> results) {
            LSTResults.DataSource = results.Results;
            LSTResults.DataBind();
        }
        private void RenderWithoutResults(SearchModel model,
                                          QueryResults<SearchResult> results) {
            // No results handling.
        }
        private void RenderCommon(SearchModel model,
                                  QueryResults<SearchResult> results) {
            // Rendering with or without results.
        }
        private QueryResults<SearchResult> ExecuteQuery(SearchModel model) {
            QueryResults<SearchResult> results;
            ISearchIndex index = ContentSearchManager.GetIndex("Coveo_web_index");
            using (var context = index.CreateSearchContext()) {
                  IQueryable<SearchResult> query = context.GetQueryable<SearchResult>()
                                                          .CoveoOr(model.Query)
                                                          .SortBy(model.SortType, model.SortDescending);
                  results = query.GetCoveoQueryResults();
            }
            return results;
        }
        private void MapControlsToModel(SearchModel model) {
            model.Query = Querybox.Text;
            model.SortDescending = SortDescending.Checked;
            model.SortType = SortList.SelectedValue;
        }
    }
    public static class SortTypes {
        public const string Date = "date";
        public const string Relevancy = "relevancy";
    }
    public class SearchModel {
        public string Query { get; set; }
        public string SortType { get; set; }
        public bool SortDescending { get; set; }
        public SearchModel() {
            Query = "";
            SortType = SortTypes.Relevancy;
            SortDescending = true;
        }
    }
    public class SearchResult {
        public DateTime Updated { get; set; }
        public DateTime Date { get; set; }
        public string Title { get; set; }
        public string PrintableURI { get; set; }
    }
    public static class QueryableSearchResultsExtensions {
        public static IQueryable<SearchResult> SortBy(this IQueryable<SearchResult> query,
                                                      string sortType,
                                                      bool isDescending) {
            switch(sortType){
                case SortTypes.Date:
                    return isDescending ? query.OrderByDescending(item => item.Updated)
                                        : query.OrderBy(item => item.Updated);
                case SortTypes.Relevancy:
                    return query;
                default:
                    throw new NotSupportedException("This sort type is not supported.");
            }
        }
    }
}