From 2e2523c38082ca601c1b0bf8d04f21d9f9afe81f Mon Sep 17 00:00:00 2001 From: Jason Dove <1695733+jasongdove@users.noreply.github.com> Date: Fri, 5 Apr 2024 09:12:46 -0500 Subject: [PATCH] another wildcard search fix (#1667) --- CHANGELOG.md | 1 + .../Search/CustomMultiFieldQueryParser.cs | 25 ++++++++++++++++--- .../Search/SearchQueryParser.cs | 6 +++++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04f7e9918..34675941a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Fixed - Fix some cases of 404s from Plex when files were replaced and scanning the library from ETV didn't help +- Fix more wildcard search phrase queries (when wildcards are used in quotes, like `title:"law & order*"`) ## [0.8.6-beta] - 2024-04-03 ### Added diff --git a/ErsatzTV.Infrastructure/Search/CustomMultiFieldQueryParser.cs b/ErsatzTV.Infrastructure/Search/CustomMultiFieldQueryParser.cs index 41bd9b2fd..1e3620157 100644 --- a/ErsatzTV.Infrastructure/Search/CustomMultiFieldQueryParser.cs +++ b/ErsatzTV.Infrastructure/Search/CustomMultiFieldQueryParser.cs @@ -3,6 +3,7 @@ using ErsatzTV.Core; using Lucene.Net.Analysis; using Lucene.Net.Index; using Lucene.Net.QueryParsers.Classic; +using Lucene.Net.QueryParsers.ComplexPhrase; using Lucene.Net.Search; using Lucene.Net.Util; using Query = Lucene.Net.Search.Query; @@ -11,8 +12,11 @@ namespace ErsatzTV.Infrastructure.Search; public class CustomMultiFieldQueryParser : MultiFieldQueryParser { - private static readonly List NumericFields = new() - { + private readonly LuceneVersion _matchVersion; + private readonly Analyzer _analyzer; + + private static readonly List NumericFields = + [ LuceneSearchIndex.MinutesField, LuceneSearchIndex.SecondsField, LuceneSearchIndex.HeightField, @@ -20,7 +24,7 @@ public class CustomMultiFieldQueryParser : MultiFieldQueryParser LuceneSearchIndex.SeasonNumberField, LuceneSearchIndex.EpisodeNumberField, LuceneSearchIndex.VideoBitDepthField - }; + ]; public CustomMultiFieldQueryParser( LuceneVersion matchVersion, @@ -28,6 +32,8 @@ public class CustomMultiFieldQueryParser : MultiFieldQueryParser Analyzer analyzer, IDictionary boosts) : base(matchVersion, fields, analyzer, boosts) { + _matchVersion = matchVersion; + _analyzer = analyzer; } public CustomMultiFieldQueryParser(LuceneVersion matchVersion, string[] fields, Analyzer analyzer) : base( @@ -35,6 +41,8 @@ public class CustomMultiFieldQueryParser : MultiFieldQueryParser fields, analyzer) { + _matchVersion = matchVersion; + _analyzer = analyzer; } protected override Query GetFieldQuery(string field, string queryText, bool quoted) @@ -90,7 +98,16 @@ public class CustomMultiFieldQueryParser : MultiFieldQueryParser // assume asterisk always means wildcard if (queryText.Contains('*')) { - return GetWildcardQuery(field, queryText); + var parser = new ComplexPhraseQueryParser(_matchVersion, LuceneSearchIndex.TitleField, _analyzer) + { + AllowLeadingWildcard = true + }; + + string queryToParse = string.IsNullOrWhiteSpace(field) + ? $"\"{queryText}\"" + : $"{field}:\"{queryText}\""; + + return parser.Parse(queryToParse); } return base.GetFieldQuery(field, queryText, slop); diff --git a/ErsatzTV.Infrastructure/Search/SearchQueryParser.cs b/ErsatzTV.Infrastructure/Search/SearchQueryParser.cs index a71702c96..2730bce02 100644 --- a/ErsatzTV.Infrastructure/Search/SearchQueryParser.cs +++ b/ErsatzTV.Infrastructure/Search/SearchQueryParser.cs @@ -3,12 +3,18 @@ using Lucene.Net.Analysis.Core; using Lucene.Net.Analysis.Miscellaneous; using Lucene.Net.Analysis.Standard; using Lucene.Net.QueryParsers.Classic; +using Lucene.Net.Search; using Query = Lucene.Net.Search.Query; namespace ErsatzTV.Infrastructure.Search; public static class SearchQueryParser { + static SearchQueryParser() + { + BooleanQuery.MaxClauseCount = 1024 * 4; + } + internal static Analyzer AnalyzerWrapper() { using var defaultAnalyzer = new CustomAnalyzer(LuceneSearchIndex.AppLuceneVersion);