Elasticsearch 6.8如何实现特定格式记录的部分匹配搜索?
针对你的Elasticsearch 6.8搜索需求,我整理了几个实用的解决方案,刚好能解决你之前通配符和ngram方案的问题:
方案1:优化通配符搜索,解决大小写敏感问题
你之前的通配符方案逻辑是对的,只是没处理大小写匹配。咱们可以通过给字段添加一个小写归一化的keyword子字段来解决:
第一步:修改字段映射
给TestRecordId字段新增一个lowercase_keyword子字段,同时定义一个小写归一器:
// 定义分析器中的归一器 .Analysis(a => a .Normalizers(n => n .Custom("lowercase_normalizer", cn => cn .Filters(new string[] { "lowercase" }) ) ) ) // 字段映射 .Text(t => t .Name(tr => tr.TestRecordId) .Fields(f => f .Keyword(k => k .Name("lowercase_keyword") .Normalizer("lowercase_normalizer") ) ) )
第二步:调整查询逻辑
查询时把用户输入转成小写,然后针对这个子字段做通配符搜索:
m => m.Wildcard(w => w .Field(tr => tr.TestRecordId.Suffix("lowercase_keyword")) .Value($"*{form.TestRecordId.ToLowerInvariant()}*") )
这样不管用户输入TR000002还是tr000002,都会统一转成小写去匹配归一化后的字段,完美解决大小写问题,同时保留通配符的子串匹配能力。
方案2:改进NGram分析器,实现精准子串匹配
你之前的ngram方案问题出在查询方式不对,用match会把查询词拆分成多个ngram去匹配,导致过度召回。咱们调整成match_phrase查询,同时优化分析器设置:
第一步:调整分析器配置
.Analysis(a => a .Analyzers(aa => aa .Custom("autocomplete", ca => ca .Tokenizer("autocomplete") .Filters(new string[] { "lowercase" }) ) .Custom("autocomplete_search", ca => ca .Tokenizer("keyword") // 搜索时把整个查询串作为单个词 .Filters(new string[] { "lowercase" }) ) ) .Tokenizers(t => t .NGram("autocomplete", e => e .MinGram(2) .MaxGram(20) // 设置为字段最长可能的长度(比如你的格式最长13位,20足够) .TokenChars(new TokenChar[] { TokenChar.Letter, TokenChar.Digit, TokenChar.Punctuation }) ) ) )
第二步:修改查询为Match Phrase
m => m.MatchPhrase(m => m .Field(tr => tr.TestRecordId) .Query(form.TestRecordId.ToLowerInvariant()) )
这样索引时会生成所有可能的连续子串(2-20位),搜索时把用户输入作为一个完整短语去匹配,只有当字段中存在完全连续的该子串时才会返回结果,既解决了大小写问题,又避免了过度召回。这个方案适合做即时搜索(输入过程中实时提示)。
方案3:使用查询字符串(Query String)查询
如果你想用更灵活的查询语法,Query String也是个不错的选择,它原生支持通配符和大小写不敏感:
第一步:字段映射
给TestRecordId设置一个带小写过滤器的分析器:
.Text(t => t .Name(tr => tr.TestRecordId) .Analyzer("lowercase") )
第二步:编写查询
m => m.QueryString(qs => qs .Fields(f => f.Field(tr => tr.TestRecordId)) .Query($"*{form.TestRecordId}*") .LowercaseExpandedTerms(true) // 自动把通配符查询转成小写 )
这个方案的好处是支持多种查询语法(比如同时搜索多个关键词),但要注意如果用户输入包含+、-等特殊字符,需要提前转义,避免影响查询逻辑。
方案对比与推荐
- 如果你不需要即时搜索,只是普通的子串搜索:**方案1(优化通配符)**最直接,实现简单,性能也不错(用keyword子字段比text字段通配符查询更快)。
- 如果需要做即时搜索(输入时实时提示):**方案2(改进NGram)**更合适,搜索响应速度快。
- 如果需要灵活的多条件搜索:**方案3(Query String)**能满足复杂需求。
内容的提问来源于stack exchange,提问作者Jordan Lewallen
相关产品推荐
相关产品推荐

