Mark Stott
Nov 19, 2021
  2110
(4 votes)

Optimizely Search Wildcard Queries and Best Bets

In a recent client build, I have been tasked with updating their search to use wild card searches.  I had read a number of posts pointing to the same solution as detailed by Joel Abrahamsson's 2012 blog post, Wildcard Queries with Episerver Find and Drew Null's post Episerver Find Wildcard Queries and Best Bets. These solutions included building an extension method that built a bool query wrapping a wild card query. This included complications in how to get best bets to work with wildcards.

While the solution did work, after reviewing the performance of the query and the structure of the query being sent to Optimizely Search and Navigation, I discovered that the solution was actually much simpler and did not need any new scaffolding of custom query building.  The For method has overloads which exposes the QueryStringQuery object that allows you to customise the query behaviour.

private ITypeSearch<T> GetQuerySearch<T>(
	string query, 
	bool isWildCardSearch) where T : MyVariant
{
	var specificQuery = isWildCardSearch ? $"*{query}*" : query;
	return _findClient.Search<T>()
                      .For(query, options =>
                      {
                          options.Query = specificQuery;
                          options.AllowLeadingWildcard = isWildCardSearch;
                          options.AnalyzeWildcard = isWildCardSearch;
                          options.RawQuery = query;
                      })
                      .InField(f => f.FieldOne, _settings.FieldOneBoost)
                      .InField(f => f.FieldTwo, _settings.FieldTwoBoost)
                      .InField(f => f.FieldThree, _settings.FieldThreeBoost)
                      .InField(f => f.FieldFour)
                      .InField(f => f.FieldFive)
                      .InField(f => f.FieldSix)
                      .InField(f => f.FieldSeven)
                      .InField(f => f.FieldEight)
                      .UsingSynonyms()
                      .UsingAutoBoost(TimeSpan.FromDays(_settings.AutoBoostTimeSpanDays))
                      .ApplyBestBets()
                      .FilterForVisitor();
}

By passing in the wild card version of the query string into options.Query and setting options.AllowLeadingWildcard and options.AnalyzeWildcard to true was all I needed for wildcard search to be functional.  I also passed in the unaltered query into options.RawQuery but this was not required in order to make Best Bets work.

The main downside to this approach is that synonym functionality no longer worked.  The query with the wildcards would never match a synonym but it would work with best bets.  I resolved this by using a Multi Search query and passed in the unaltered query and then the wild card query.  In Multi Search, each result set is returned in the same order in which it has been defined and they are packaged in a single API call.  It was then a simple case of selecting the first result set with at least one match.

var searchResult _findClient.MultiSearch<DentalVariantProjectionModel>()
                                            .Search<MyVariant, MyProjectionModel>(x => GetQuerySearch(query, false))
                                            .Search<MyVariant, MyProjectionModel>(x => GetQuerySearch(query, true))
                                            .GetResult();

var resultToUse = searchResult.FirstOrDefault(x => x.TotalMatching > 0) ?? searchResult.First();

Performance wise, the difference in sending two queries in a multi search request was negligable compared to a sending a single query.

Nov 19, 2021

Comments

Please login to comment.
Latest blogs
Opti ID overview

Opti ID allows you to log in once and switch between Optimizely products using Okta, Entra ID, or a local account. You can also manage all your use...

K Khan | Jul 26, 2024

Getting Started with Optimizely SaaS using Next.js Starter App - Extend a component - Part 3

This is the final part of our Optimizely SaaS CMS proof-of-concept (POC) blog series. In this post, we'll dive into extending a component within th...

Raghavendra Murthy | Jul 23, 2024 | Syndicated blog

Optimizely Graph – Faceting with Geta Categories

Overview As Optimizely Graph (and Content Cloud SaaS) makes its global debut, it is known that there are going to be some bugs and quirks. One of t...

Eric Markson | Jul 22, 2024 | Syndicated blog

Integration Bynder (DAM) with Optimizely

Bynder is a comprehensive digital asset management (DAM) platform that enables businesses to efficiently manage, store, organize, and share their...

Sanjay Kumar | Jul 22, 2024

Frontend Hosting for SaaS CMS Solutions

Introduction Now that CMS SaaS Core has gone into general availability, it is a good time to start discussing where to host the head. SaaS Core is...

Minesh Shah (Netcel) | Jul 20, 2024

Optimizely London Dev Meetup 11th July 2024

On 11th July 2024 in London Niteco and Netcel along with Optimizely ran the London Developer meetup. There was an great agenda of talks that we put...

Scott Reed | Jul 19, 2024