Coveo For Sitecore: Introduction To Using LINQ

The ContentSearch API Delivers

Sitecore 7 introduced the concept of the ContentSearch API and with it, swappable ContentSearch providers. This is a very exciting concept.

Coveo for Sitecore has taken this concept and ran with it. Coveo has created full-featured search engine,a JavaScript-based UI and REST API in addition to being ContentSearch API provider.

To illustrate a Coveo-powered ContentSearch, I'll share two examples. The first one will illustrate how transparent using Coveo for ContentSearch can be. The second will highlight enhanced LINQ functionality provided by Coveo.

Coveo Is Transparent To Use

Even though it's Coveo-powered, it looks exactly like an OOTB Lucene-based ContentSearch query. And that's the point. Applause to the Sitecore and Coveo team for this.

Here is a simple example:


using System.Collections.Generic;
using System.Linq;
using Sitecore.ContentSearch;
using Sitecore.ContentSearch.Security;
using Sitecore.Data;
using Fishtank.Domain; // reference for BlogItem

namespace Fishtank.Repository
{
    public class BlogRepository
    {
        public List<BlogItem> GetRelatedItems(ID tagId)
        {
            if(ID.IsNullOrEmpty(tagId)) return new List<BlogItem>();

            // Default name of the the web index w/ Coveo
            var searchIndex = ContentSearchManager.GetIndex("coveo_web_index");

            // SearchSecurityOptions are optional, defaults to "EnableSecurityCheck"
            using (
                var context =
                    searchIndex.CreateSearchContext(SearchSecurityOptions.DisableSecurityCheck))
            {
                // Execute standard ContentSearch LINQ query
                // BlogItem inherits SearchResultItem
                var posts = context.GetQueryable<BlogItem>().Where(
                        i => i.RelatedContentIds.Contains(tagId)
                    ).ToList();

                return posts;
            }
        }
    }   
}

For completeness, this is the BlogItem class references above:


// "using" statements excluded
namespace Fishtank.Domain
{
    public class BlogItem : SearchResultItem
    {
        [IndexField("RelatedContent")]
        [TypeConverter(typeof(IndexFieldEnumerableConverter))]
        public virtual IEnumerable<ID> RelatedContentIds { get; set; }
    }  
}

And the configuration added to the <FieldMap> to pull in RelatedContent: (Simplified over Lucene, IMO).


<fieldType fieldName="RelatedContent" isMultiValue="true" isSortable="false" isFacet="false" includeForFreeTextSearch="false" settingType='Coveo.Framework.Configuration.FieldConfiguration, Coveo.Framework' />

Coveo-Enhanced LINQ Query

Adding using Coveo.SearchProvider.Linq; to the BlogRepository class adds new Coveo LINQ methods, implemented as extension methods.

CoveoBoost()
Boosting allows to ContentSearch result to be sorted in a more organic, less linear manner. It introduces the concept of relevance to LINQ.


var posts = context.GetQueryable<BlogItem>()
    .Where(i => i.TemplateName == "Blog")
    .CoveoBoost(i => i.Name.Contains("Sitecore"), 25)
    .CoveoBoost(i => i["featured"] == "1", 25)
    .ToList();                

Any posts marked as "featured" or containing "Sitecore" in the title are boosted in the results.

Other LINQ methods Coveo supports

PhoneticMatch: Matches text based on sound
.Where(i => i["field"].PhoneticMatch("purson")

ContainsKeywords(string): Matches against indexed page content
.Where(i => i["field"].ContainsKeywords("Sitecore")

ExactMatch(string): Matches against exact indexed page content
.Where(i => i["field"].ExactMatch("Sitecore")

CoveoIn(): Execute nested queries. (I'll address this one separately, sorry)

I hope this was enough to help you get started.

This post with authored using Markdown for Sitecore.

Fish