如何使用elasticsearch对文本输入执行部分单词搜索?

bz4sfanl  于 2021-06-14  发布在  ElasticSearch
关注(0)|答案(1)|浏览(566)

我有一个查询用于搜索以下格式的记录: TR000002_1_2020 .
用户应该能够通过以下方式搜索结果: TR000002 或者 2_1_2020 或者 TR000002_1_2020 或者 2020 . 我使用的是elasticsearch 6.8,因此无法使用e7中引入的内置搜索。因此,我想 wildcard 搜索或 ngram 也许最适合我的需要。以下是我的两种方法以及它们不起作用的原因。
通配符
属性Map:

  1. .Text(t => t
  2. .Name(tr => tr.TestRecordId)
  3. )

查询:

  1. m => m.Wildcard(w => w
  2. .Field(tr => tr.TestRecordId)
  3. .Value($"*{form.TestRecordId}*")
  4. ),

这是可行的,但它是区分大小写的,因此如果用户使用 tr000002_1_2020 ,则不会返回任何结果(因为 t 以及 r (在查询中小写)
ngram(键入时搜索)
创建自定义ngram分析器

  1. .Analysis(a => a
  2. .Analyzers(aa => aa
  3. .Custom("autocomplete", ca => ca
  4. .Tokenizer("autocomplete")
  5. .Filters(new string[] {
  6. "lowercase"
  7. })
  8. )
  9. .Custom("autocomplete_search", ca => ca
  10. .Tokenizer("lowercase")
  11. )
  12. )
  13. .Tokenizers(t => t
  14. .NGram("autocomplete", e => e
  15. .MinGram(2)
  16. .MaxGram(16)
  17. .TokenChars(new TokenChar[] {
  18. TokenChar.Letter,
  19. TokenChar.Digit,
  20. TokenChar.Punctuation,
  21. TokenChar.Symbol
  22. })
  23. )
  24. )
  25. )

属性Map

  1. .Text(t => t
  2. .Name(tr => tr.TestRecordId)
  3. .Analyzer("autocomplete")
  4. .SearchAnalyzer("autocomplete_search")
  5. )

查询

  1. m => m.Match(m => m
  2. .Query(form.TestRecordId)
  3. ),

正如这个答案中所描述的,这不起作用,因为标记器将字符拆分为如下元素 20 以及 02 以及 2020 ,因此查询返回索引中包含2020的所有文档,例如 TR000002_1_2020 以及 TR000008_1_2020 以及 TR000003_6_2020 .
elasticsearch的最佳利用是什么,以允许我所需的搜索行为?我见过 query string 也用过。谢谢!

ryevplcw

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和分析的示例。它不在巢里,但我想你能翻译出来。

  1. PUT pattern_split_demo
  2. {
  3. "settings": {
  4. "analysis": {
  5. "char_filter": {
  6. "replace_char_filter": {
  7. "type": "pattern_replace",
  8. "pattern": "^TR0*",
  9. "replacement": ""
  10. }
  11. },
  12. "tokenizer": {
  13. "split_tokenizer": {
  14. "type": "simple_pattern_split",
  15. "pattern": "_"
  16. }
  17. },
  18. "analyzer": {
  19. "split_analyzer": {
  20. "tokenizer": "split_tokenizer",
  21. "filter": [
  22. "lowercase"
  23. ],
  24. "char_filter": [
  25. "replace_char_filter"
  26. ]
  27. }
  28. }
  29. }
  30. },
  31. "mappings": {
  32. "properties": {
  33. "content": {
  34. "type": "text",
  35. "analyzer": "split_analyzer"
  36. }
  37. }
  38. }
  39. }
  40. POST pattern_split_demo/_analyze
  41. {
  42. "text": "TR000002_1_2020",
  43. "analyzer": "split_analyzer"
  44. } => ["2", "1", "2020"]
  45. POST pattern_split_demo/_doc?refresh=true
  46. {
  47. "content": "TR000002_1_2020"
  48. }
  49. POST pattern_split_demo/_search
  50. {
  51. "query": {
  52. "match_phrase": {
  53. "content": "TR000002_1_2020"
  54. }
  55. }
  56. }
展开查看全部

相关问题