When using a wildcard in your search query like ‘search.For(query+”*”)’ or when you used the reversed method suggested in the Breaking changes article Best Bets and Synonyms will stop working/will not work as they do a lookup on the query in the request.
The Best Bets can be “fixed” by using a custom IPhraseCriterion like below and register it
[EPiServerDataStore(
AutomaticallyRemapStore = true,
AutomaticallyCreateStore = true,
StoreName = "EPiServer.Find.Framework.BestBets.DefaultPhraseCriterion"
)]
public class WildCardPhraseCriterion : DefaultPhraseCriterion, IPhraseCriterion
{
public override bool Match(string searchPhrase)
{
if (string.IsNullOrWhiteSpace(searchPhrase) || Phrase == null)
{
return false;
}
// Remove wildcard
string cleanedSearchPhrase = searchPhrase.Replace("*", string.Empty).Replace("?", string.Empty);
return base.Match(cleanedSearchPhrase);
}
}
For the synonyms you will need to create a custom version of the extension within Find. Though I think this overload should be in the QueryStringSearchExtensions of Find by default.
public static IQueriedSearch<TSource, QueryStringQuery> UsingSynonyms<TSource>(
this IQueriedSearch<TSource> search, string queryString)
{
search.ValidateNotNullArgument(nameof (search));
if (search.Client.Settings.Admin)
{
return new Search<TSource, QueryStringQuery>(search, context =>
{
if (!(context.RequestBody.Query is QueryStringQuery query2))
{
Trace.Instance.Add(new TraceEvent(search, "The use of synonyms are only supported för QueryStringQueries, i.e. with the use of the .For() -extensions. The query will be executed without the use of synonyms.")
{
IsError = false
});
}
else
{
string str = queryString ?? string.Empty;
((QueryStringQuery) context.RequestBody.Query).Query = str.Replace(' ', '¤');
MultiFieldQueryStringQuery queryStringQuery = query2 as MultiFieldQueryStringQuery;
if (queryStringQuery.IsNull())
{
((QueryStringQuery) context.RequestBody.Query).Analyzer = "synonym";
}
else if (queryStringQuery.Fields.Except<string>(["_all"]).Any<string>())
{
((QueryStringQuery) context.RequestBody.Query).Analyzer = context.Analyzer?.SynonymQueryAnalyzer;
}
else
{
((QueryStringQuery) context.RequestBody.Query).Analyzer = "synonym";
}
}
});
}
Trace.Instance.Add(new TraceEvent(search, "Your index does not support synonyms. Please contact support to have your account upgraded. Falling back to search without synonyms.")
{
IsError = false
});
return new Search<TSource, QueryStringQuery>(search, context => { });
}
Or just do the cleaning up of your query in the extension, which most of us have done I think
public static IQueriedSearch<TSource, QueryStringQuery> UsingSynonyms<TSource>(
this IQueriedSearch<TSource> search)
{
search.ValidateNotNullArgument(nameof (search));
if (search.Client.Settings.Admin)
return (IQueriedSearch<TSource, QueryStringQuery>) new Search<TSource, QueryStringQuery>((ISearch) search, (Action<ISearchContext>) (context =>
{
if (!(context.RequestBody.Query is QueryStringQuery query2))
{
Trace.Instance.Add((ITraceEvent) new TraceEvent((ITraceable) search, "The use of synonyms are only supported för QueryStringQueries, i.e. with the use of the .For() -extensions. The query will be executed without the use of synonyms.")
{
IsError = false
});
}
else
{
string str = (query2.Query ?? (FieldFilterValue) string.Empty).ToString();
// If you used the reverse method as described in https://docs.developers.optimizely.com/digital-experience-platform/v1.1.0-search-and-navigation/docs/breaking-changes-for-find15
// You will need to reverse that again, else no match will be found ever
// new string(searchPhrase.Reverse().ToArray())
// Remove wildcard
string cleanedSearchPhrase = str.Replace("*", string.Empty).Replace("?", string.Empty);
((QueryStringQuery) context.RequestBody.Query).Query = (FieldFilterValue) cleanedSearchPhrase.Replace(' ', '¤');
MultiFieldQueryStringQuery queryStringQuery = query2 as MultiFieldQueryStringQuery;
if (queryStringQuery.IsNull())
((QueryStringQuery) context.RequestBody.Query).Analyzer = "synonym";
else if (queryStringQuery.Fields.Except<string>((IEnumerable<string>) new string[1]
{
"_all"
}).Any<string>())
((QueryStringQuery) context.RequestBody.Query).Analyzer = context.Analyzer?.SynonymQueryAnalyzer;
else
((QueryStringQuery) context.RequestBody.Query).Analyzer = "synonym";
}
}));
Trace.Instance.Add((ITraceEvent) new TraceEvent((ITraceable) search, "Your index does not support synonyms. Please contact support to have your account upgraded. Falling back to search without synonyms.")
{
IsError = false
});
return (IQueriedSearch<TSource, QueryStringQuery>) new Search<TSource, QueryStringQuery>((ISearch) search, (Action<ISearchContext>) (context => { }));
}
There’s also a gist with the snippets