2

Can we adjust the Lucene search results so that items most likely to be related are shown closer to the top of the results feed - I'm thinking this would involve providing higher weight to results with matches in a page title field vs. Results with matches in a body field.

Update: I've made the changes suggested, and it has helped but my goal is to get anything with a word in the title to come up first before anything that doesn't have the word in it (but maybe in some other field such as the body. This isn't what happens currently even when specifying a very large boost value I get a few items intermixed that don't have the given word in the title. I had to alter the code slightly to get it working without our model, but here's what I have:

public List<CustomSearchResultItem> GetSiteSearchNew(string searchQuery)
    {
        string indexName = App.Core.Config.SettingsManager.GetSetting("SearchIndexName");
        var index = Sitecore.ContentSearch.ContentSearchManager.GetIndex(indexName);
        var db = Sitecore.Context.Database;

        Sitecore.Diagnostics.Error.AssertNotNull(index,
            "There is no " + indexName + " index on the current database (" + db.Name + ")");

        using (var context = index.CreateSearchContext())
        {
            var baseQuery = context.GetQueryable<CustomSearchResultItem>();

            var query = PredicateBuilder.True<CustomSearchResultItem>();

            if (!string.IsNullOrWhiteSpace(searchQuery))
            {
                // boost specific search matches
                //query = query.Or(item => item.Title == searchQuery).Boost(1350);

                // optionally, split up query to find matches on each word
                foreach (var word in searchQuery.Split(' '))
                {
                    query = query.Or(item => item.Title.Contains(word)).Boost(9350);


                }
            }

            baseQuery = baseQuery.Where(query);

            // pagination, etc.

            var results = baseQuery.ToList();

            return results;

            // return results or map to a DTO, etc.
        }
    }
9

There's a bit of plumbing you need in place first. Assuming you're already somewhat familiar with the Content Search API, the core of your question is answered below.

Custom Search Result Item

This is needed in order to access the Title field you are referencing. Example implies a field name of "My Title".

public class CustomSearchResultItem : SearchResultItem
{
    [DataMember]
    [IndexField("my_title")]
    public string Title { get; set; }
}

Search Logic

var index = ContentSearchManager.GetIndex("my index");

using (var context = index.CreateSearchContext())
{
    var baseQuery = context.GetQueryable<CustomSearchResultItem>();

    var query = PredicateBuilder.True<CustomSearchResultItem>();

    if (!string.IsNullOrWhiteSpace(searchQuery))
    {
        // boost specific search matches
        query = query.Or(item => item.Title == searchQuery).Boost(50);

        // optionally, split up query to find matches on each word
        foreach (var word in searchQuery.Split(' '))
        {
            query = query.Or(item => item.Title.Contains(word)); 
        }
    }

    baseQuery = baseQuery.Where(query);

    // pagination, etc.

    var results = baseQuery.GetResults();

    // return results or map to a DTO, etc.
}

What you're mainly after is the Boost feature. My goto boost is typically 50 and seems to work well.

My main rule-of-thumb is to boost results that are an exact match (even on a content field), and then split the query into individual words for additional results.

Assemblies required:

  • Sitecore.ContentSearch.dll
  • Sitecore.ContentSearch.Linq.dll
| improve this answer | |
  • 1
    You beat me to the answer :-) – Dylan Young Nov 21 '18 at 19:32
  • Thanks. When I try this, though, I have a number of complaints from intellisense: containsQuery does not exist in the current context - where is it being defined? – Levi Wallach Nov 21 '18 at 20:36
  • Also query.GetResultss() - 'Expression<Func<SearchHelper.CustomSearchResultItem, bool>>' does not contain a definition for 'GetResults' and no extension method 'GetResults' accepting a first argument of type 'Expression<Func<SearchHelper.CustomSearchResultItem, bool>>' could be found (are you missing a using directive or an assembly reference?) – Levi Wallach Nov 21 '18 at 20:37
  • Finally for [DataMember] it's saying it could not be found. I tried removing and readding System.runtime.serialization but that didn't fix the complaint from intellisense... – Levi Wallach Nov 21 '18 at 20:38
  • 1
    Just wanted to add that you can not boost wild card queries (aka Contains). So you can never boost the line "query = query.Or(item => item.Title.Contains(word));" – Chris Auer Nov 22 '18 at 4:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.