【发布时间】:2020-12-27 15:31:42
【问题描述】:
我有一个查询要搜索以下格式的记录:TR000002_1_2020。
用户应该能够通过以下方式搜索结果:
TR000002 或 2_1_2020 或 TR000002_1_2020 或 2020。我使用的是 Elasticsearch 6.8,所以我不能使用 E7 中引入的内置 Search-As-You-Type。因此,我认为wildcard 搜索或ngram 可能最适合我的需要。以下是我的两种方法以及为什么它们不起作用。
- 通配符
属性映射:
.Text(t => t
.Name(tr => tr.TestRecordId)
)
查询:
m => m.Wildcard(w => w
.Field(tr => tr.TestRecordId)
.Value($"*{form.TestRecordId}*")
),
这可行,但它区分大小写,因此如果用户使用tr000002_1_2020 搜索,则不会返回任何结果(因为t 和r 在查询中是小写的)
- ngram(键入时搜索等效项)
创建自定义 ngram 分析器
.Analysis(a => a
.Analyzers(aa => aa
.Custom("autocomplete", ca => ca
.Tokenizer("autocomplete")
.Filters(new string[] {
"lowercase"
})
)
.Custom("autocomplete_search", ca => ca
.Tokenizer("lowercase")
)
)
.Tokenizers(t => t
.NGram("autocomplete", e => e
.MinGram(2)
.MaxGram(16)
.TokenChars(new TokenChar[] {
TokenChar.Letter,
TokenChar.Digit,
TokenChar.Punctuation,
TokenChar.Symbol
})
)
)
)
属性映射
.Text(t => t
.Name(tr => tr.TestRecordId)
.Analyzer("autocomplete")
.SearchAnalyzer("autocomplete_search")
)
查询
m => m.Match(m => m
.Query(form.TestRecordId)
),
正如in this answer 所述,这不起作用,因为标记器将字符拆分为20 和02 和2020 等元素,因此我的查询返回了我的索引中包含的所有文档2020 年,例如 TR000002_1_2020 和 TR000008_1_2020 和 TR000003_6_2020。
什么是 Elasticsearch 的最佳利用方式来实现我想要的搜索行为?我也看到query string 被使用过。谢谢!
【问题讨论】:
-
TR000002_1_2020格式是否有一些通用模式,即可以从正则表达式中识别出来的模式? -
@RussCam 嗯,所以该字符串中唯一一致的部分是
TR。000002将递增(称为测试记录编号),_1_是任务编号,因此会发生变化,2020是年份,因此显然也会递增 -
好的,那么像
TR\d+_\d+_\d+这样的模式会起作用吗?我认为模式标记器与带状疱疹和小写标记过滤器结合使用可能是一种有效的方法
标签: elasticsearch nest elasticsearch-6