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

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

我有一个查询用于搜索以下格式的记录: 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 也用过。谢谢!

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

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"
    }
  }
}

相关问题