我有一个查询用于搜索以下格式的记录: TR000002_1_2020
.
用户应该能够通过以下方式搜索结果: TR000002
或者 2_1_2020
或者 TR000002_1_2020
或者 2020
. 我使用的是elasticsearch 6.8,因此无法使用e7中引入的内置搜索。因此,我想 wildcard
搜索或 ngram
也许最适合我的需要。以下是我的两种方法以及它们不起作用的原因。
通配符
属性Map:
.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
})
)
)
)
属性Map
.Text(t => t
.Name(tr => tr.TestRecordId)
.Analyzer("autocomplete")
.SearchAnalyzer("autocomplete_search")
)
查询
m => m.Match(m => m
.Query(form.TestRecordId)
),
正如这个答案中所描述的,这不起作用,因为标记器将字符拆分为如下元素 20
以及 02
以及 2020
,因此查询返回索引中包含2020的所有文档,例如 TR000002_1_2020
以及 TR000008_1_2020
以及 TR000003_6_2020
.
elasticsearch的最佳利用是什么,以允许我所需的搜索行为?我见过 query string
也用过。谢谢!
1条答案
按热度按时间ryevplcw1#
这里有一个简单的方法来满足您的要求(我希望如此)。
我们使用模式替换字符过滤器来删除引用的固定部分(tr000…)
我们使用拆分标记器来拆分“\”字符上的引用
我们使用匹配短语查询来确保引用片段按顺序匹配
以此分析链为参考
TR000002_1_2020
我们拿到代币了["2", "1", "2020" ]
. 因此它将匹配查询["TR000002_1_2020", "TR000002 1 2020", "2_1_2020", "1_2020"]
,但不匹配3_1_2020
或者2_2_2020
.下面是一个Map和分析的示例。它不在巢里,但我想你能翻译出来。