如何解决如何使用Elasticsearch对输入的文本执行部分单词搜索?
我有一个查询来搜索以下格式的记录:TR000002_1_2020
。
TR000002
或2_1_2020
或TR000002_1_2020
或2020
。我正在使用Elasticsearch 6.8,所以无法使用E7中引入的内置“按类型输入”功能。因此,我认为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
的使用。谢谢!
解决方法
这是一种满足您要求的简单方法(希望如此)。
- 我们使用模式替换char过滤器删除参考(TR000 ...)的固定部分
- 我们使用拆分标记器将引用中的“ _”字符拆分为
- 我们使用matchPhrase查询来确保引用的片段顺序匹配
使用此分析链作为参考TR000002_1_2020
,我们获得了令牌["2","1","2020" ]
。因此它将与查询["TR000002_1_2020","TR000002 1 2020","2_1_2020","1_2020"]
相匹配,但与3_1_2020
或2_2_2020
不匹配。
这里是映射和分析的示例。它不在Nest中,但我认为您可以进行翻译。
PUT pattern_split_demo
{
"settings": {
"analysis": {
"char_filter": {
"replace_char_filter": {
"type": "pattern_replace","pattern": "^TR0*","replacement": ""
}
},"tokenizer": {
"split_tokenizer": {
"type": "simple_pattern_split","pattern": "_"
}
},"analyzer": {
"split_analyzer": {
"tokenizer": "split_tokenizer","filter": [
"lowercase"
],"char_filter": [
"replace_char_filter"
]
}
}
}
},"mappings": {
"properties": {
"content": {
"type": "text","analyzer": "split_analyzer"
}
}
}
}
POST pattern_split_demo/_analyze
{
"text": "TR000002_1_2020","analyzer": "split_analyzer"
} => ["2","2020"]
POST pattern_split_demo/_doc?refresh=true
{
"content": "TR000002_1_2020"
}
POST pattern_split_demo/_search
{
"query": {
"match_phrase": {
"content": "TR000002_1_2020"
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。