Predictive search

There is a new version of the search functionality in Relatude. This new search has built in support for automatic search suggestions based on spellchecking and synonymes.

To make use of this new functionality, first generate your normal index query object like this:

var query = new IndexQuery<ContentBase>();
query.BodySearch = search;
query.PageIndex = pageIndex;
query.PageSize = _pageSize;

 

You then create the new search object like this:

var advancedQuery = new AdvancedIndexQuery<ContentBase>(query);

 

You then have the option of turning on suggestions:

advancedQuery.SuggestDifferentSpelling = true;
advancedQuery.SuggestSynonyms = true;

 

To perform the search you call the usual method:

var results = WAFContext.Session.SearchAdvanced<ContentBase>(advancedQuery);

 

The result object now contains a result description property that contains a text that suggest alternative searches to the user. This text also contains links that will perform new searches.

 

To display the text you could do this:

html.Append(results.ResultDescription);

 

If you want to customize this text you can modify the templates:

advancedQuery.TextTemplates...

 

Here are the default values:

NoHits = "Your search gave <b>no</b> hits. ";
OneHit = "Your search gave <b>1</b> hit. ";
MultipleHits = "Your search gave <b>[HITCOUNT]</b> hits. ";
ShowingResultFor = "Showing results for <a href=\"?q=[TERM_URLENCODED]\"><b>[TERM]</b></a> with <b>1</b> hit. ";
ShowingResultsFor = "Showing results for <a href=\"?q=[TERM_URLENCODED]\"><b>[TERM]</b></a> with <b>[HITCOUNT]</b> hits. ";
Correction = "Did you mean: [TERMS]. ";
Synonyme = "Related: [TERMS]. ";
Corrections = "Did you mean: [TERMS]. ";
Synonymes = "Related: [TERMS]. ";
LinkTemplate = "<a href=\"?q=[TERM_URLENCODED]\" title=\"[HITCOUNT] hits\">[TERM]</a>";

 

An example of the search functionality:

http://www.webnodes.com/search?q=hiercal

You will here see an example of both spellcheck and synonymes.

Here is the source code for a complete search page:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:TextBox runat="server" ID="txtSearch"></asp:TextBox>
            <asp:Button ID="btnSearch" OnClick="btnSearch_Click" runat="server" Text="Search" />
            <asp:Literal runat="server" ID="litResult" EnableViewState="false"></asp:Literal>
        </div>
    </form>
</body>
</html>
using System;
using System.Text;
using System.Web;
using WAF.Engine;
using WAF.Engine.Content;
using WAF.Presentation.Web;

public partial class _Default : System.Web.UI.Page
{
    string _qSearch = "q";
    string _qPage = "page";
    int _pageSize = 10;
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            string search = Request[_qSearch];
            if (search != null)
            {
                litResult.Text = getSearchHtml(search);
                txtSearch.Text = search;
            }
        }
    }
    protected void btnSearch_Click(object sender, EventArgs e)
    {
        txtSearch.Text = txtSearch.Text.Trim();
        if (txtSearch.Text.Length > 0)
        {
            var qs = _qSearch + "=" + HttpUtility.UrlEncode(txtSearch.Text);
            Response.Redirect(WAFContext.GetUrl(WAFContext.Request.NodeId, qs));
        }
    }
    protected string getSearchHtml(string search)
    {
        StringBuilder html = new StringBuilder();
        if (search == null) return "";
        int pageIndex = 0;
        if (int.TryParse(Request["page"], out pageIndex)) pageIndex--;
        try
        {
            var query = new IndexQuery<ContentBase>();
            query.BodySearch = search;
            query.PageIndex = pageIndex;
            query.PageSize = _pageSize;

            var advancedQuery = new AdvancedIndexQuery<ContentBase>(query);
            advancedQuery.SuggestDifferentSpelling = true;
            advancedQuery.SuggestSynonyms = true;
            var results = WAFContext.Session.SearchAdvanced<ContentBase>(advancedQuery);

            html.Append("<br/><br/><div>");
            html.Append(results.ResultDescription);
            html.Append("</div>");

            //html.Append("<div style=\"margin-top:10px;\">Your search gave <strong>");
            //html.Append(results.TotalCount);
            //html.Append("</strong> hit" + (results.TotalCount == 1 ? "" : "s"));
            //html.Append(": ");
            //html.Append("</div>");
            if (pageIndex >= results.PageCount) pageIndex = results.PageCount - 1;
            string pagingHtml = getPageHtml(_pageSize, results.PageCount, pageIndex, search);
            if (pagingHtml != null) html.Append(pagingHtml);
            foreach (var result in results.Hits)
            {
                html.Append("<div style=\"margin-top:10px;\"><a href=\"");
                html.Append(HttpUtility.HtmlAttributeEncode(WAFContext.GetUrl(result.Content)));
                html.Append("\">");
                html.Append(result.FormatSample(HttpUtility.HtmlEncode(result.Name), 160,
                "<span style=\"font-weight:bold; font-style:italic; font-size:16px;\">", "</span>"));
                html.Append("</a></div>");
                html.Append("<div style=\"font-size:12px;\">");
                html.Append(result.FormatSample(HttpUtility.HtmlEncode(result.Body), 160,
                "<span style=\"font-weight:bold; font-style:italic; font-size:14px;\">", "</span>"));
                html.Append("</div>");
            }
            if (pagingHtml != null) html.Append(pagingHtml);
        }
        catch (Exception error)
        {
            html.Append("<div style=\"color:gray; margin-top:10px;\">INVALID SEARCH: " + error.Message + "</div>");
        }
        return html.ToString();
    }
    string getPageHtml(int pageSize, int pageCount, int pageIndex, string search)
    {
        if (pageCount < 2) return null;
        StringBuilder html = new StringBuilder();
        html.Append("<div style=\"margin-top:10px;\">");
        html.Append("PAGES: ");
        for (int i = 1; i <= pageCount; i++)
        {
            html.Append("<a style=\"padding: 3px;");
            if (i - 1 == pageIndex) html.Append("font-weight:bold;");
            html.Append("\" href=\"");
            var qs = _qSearch + "=" + HttpUtility.UrlEncode(search) + "&" + _qPage + "=" + i;
            html.Append(WAFContext.GetUrl(WAFContext.Request.NodeId, qs));
            html.Append("\">");
            html.Append("[");
            html.Append(i);
            html.Append("]");
            html.Append("</a>");
        }
        html.Append("</div>");
        return html.ToString();
    }
}