elasticsearch 如何使用Elasticsearch对文本输入执行部分单词搜索?,elasticsearch,nest,elasticsearch-6,elasticsearch,Nest,Elasticsearch 6" /> elasticsearch 如何使用Elasticsearch对文本输入执行部分单词搜索?,elasticsearch,nest,elasticsearch-6,elasticsearch,Nest,Elasticsearch 6" />

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

elasticsearch 如何使用Elasticsearch对文本输入执行部分单词搜索?,elasticsearch,nest,elasticsearch-6,elasticsearch,Nest,Elasticsearch 6,我有一个查询来搜索以下格式的记录:TR000002\u 1\u 2020 用户应能够通过以下方式搜索结果: TR000002或2\u 1\u 2020或TR000002\u 1\u 2020或2020。我使用的是Elasticsearch 6.8,因此我无法使用E7中引入的内置搜索。因此,我认为通配符搜索或ngram可能最适合我的需要。以下是我的两种方法以及它们不起作用的原因 通配符 属性映射: .Text(t => t .Name(tr => tr.TestRecordId

我有一个查询来搜索以下格式的记录:
TR000002\u 1\u 2020

用户应能够通过以下方式搜索结果:

TR000002
2\u 1\u 2020
TR000002\u 1\u 2020
2020
。我使用的是Elasticsearch 6.8,因此我无法使用E7中引入的内置搜索。因此,我认为
通配符
搜索或
ngram
可能最适合我的需要。以下是我的两种方法以及它们不起作用的原因

  • 通配符
  • 属性映射:

    .Text(t => t
        .Name(tr => tr.TestRecordId)
    )
    
    查询:

    m => m.Wildcard(w => w
        .Field(tr => tr.TestRecordId)
        .Value($"*{form.TestRecordId}*")
    ),
    
    这是可行的,但它区分大小写,因此如果用户使用
    tr000002\u 1\u 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")
    )
    
    质疑

    如上所述,这不起作用,因为标记器将字符拆分为元素,如
    20
    02
    2020
    ,因此我的查询返回了我索引中包含2020的所有文档,如
    TR000002\u 1\u 2020
    tr00008\u 1\u 2020
    tr00003\u 6\u 2020


    Elasticsearch的最佳用途是什么,以允许我进行所需的搜索行为?我还看到使用了
    查询字符串
    。谢谢

    这里有一个简单的方法来满足您的需求(我希望如此)

  • 我们使用模式替换字符过滤器来删除引用的固定部分(TR000…)
  • 我们使用拆分标记器拆分“\u1”字符上的引用
  • 我们使用匹配短语查询来确保引用的片段按顺序匹配
  • 利用该分析链作为参考
    TR000002_1_2020
    我们得到了令牌
    [“2”、“1”、“2020”]
    。因此,它将匹配查询
    [“TR000002\u 1\u 2020”、“TR000002 1 2020”、“2\u 1\u 2020”、“1\u 2020”]
    ,但不会匹配
    3\u 1\u 2020
    2\u 2020

    下面是一个映射和分析的示例。它不在巢里,但我想你能翻译出来

    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", "1", "2020"]
    
    POST pattern_split_demo/_doc?refresh=true
    {
      "content": "TR000002_1_2020"
    }
    
    POST pattern_split_demo/_search
    {
      "query": {
        "match_phrase": {
          "content": "TR000002_1_2020"
        }
      }
    }
    

    格式
    TR000002_1_2020
    是否有一些通用模式,即可以从正则表达式中辨别出来的模式?@RussCam-hmm因此,该字符串中唯一一致的部分是
    TR
    000002
    会增加(它被称为测试记录编号),
    u1
    是任务编号,因此会发生变化,
    2020
    是年份,因此也会明显增加,所以像
    TR\d+\ud+\ud+
    这样的模式会起作用吗?我认为模式标记器与木瓦和小写标记过滤器相结合可能是一种有效的方法
    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", "1", "2020"]
    
    POST pattern_split_demo/_doc?refresh=true
    {
      "content": "TR000002_1_2020"
    }
    
    POST pattern_split_demo/_search
    {
      "query": {
        "match_phrase": {
          "content": "TR000002_1_2020"
        }
      }
    }