ElasticSearch "H & R Block" 带有部分词搜索

ElasticSearch "H & R Block" with partial word search

要求是能够搜索到以下词条:

  1. "H & R" 找到 "H & R Block".

我已经设法单独使用 word_delimiter 实现了这个要求,正如这个答案 elasticsearch tokenize "H&R Blocks" as "H", "R", "H&R", "Blocks"

中提到的

使用 ruby 代码:

{
  char_filter: {
    strip_punctuation: { type: "mapping", mappings: [".=>", ",=>", "!=>", "?=>"] },
  },
  filter: {
    my_splitter: { 
      type: "word_delimiter", 
      preserve_original: true 
    }
  },
  analyzer: {
    my_analyzer {
      char_filter: %w[strip_punctuation],
      type: "custom",
      tokenizer: "whitespace",
      filter: %w[lowercase asciifolding my_splitter]
    }
  }
}

而且,在同一个查询中,我们需要自动完成功能或部分单词匹配,所以

  1. "Ser"、"Serv"、"Servi"、"Servic" 和 "Service" 都可以找到 "Service" 和 "Services"。

我已经成功地使用 ngram 单独实现了这个要求。

{
  char_filter: {
    strip_punctuation: { type: "mapping", mappings: [".=>", ",=>", "!=>", "?=>"] }
  },
  analyzer: {
    my_analyzer: {
      char_filter: %w[strip_punctuation],
      tokenizer: "my_ngram",
      filter: %w[lowercase asciifolding]
    }
  },
  tokenizer: {
    my_ngram: {
      type: "nGram",
      min_gram: "3",
      max_gram: "10",
      token_chars: %w[letter digit]
    }
  } 
}

我只是无法同时实施它们。当我使用 ngram 时,短词会被忽略,所以 "H & R" 被忽略了。当我使用 word_delimiter 时,部分单词搜索停止工作。下面,我最近尝试合并这两个要求,结果支持部分单词搜索但不支持 "H & R"。

{
  char_filter: {
    strip_punctuation: { type: "mapping", mappings: [".=>", ",=>", "!=>", "?=>"] }
  },
  filter: {
    my_splitter: {
      type: "word_delimiter",
      preserve_original: true
    }
  },
  analyzer: {
    my_analyzer: {
      char_filter: %w[strip_punctuation],
      type: "custom",
      tokenizer: "my_tokenizer",
      filter: %w[lowercase asciifolding my_splitter]
    }
  },
  tokenizer: {
    my_tokenizer: {
      type: "nGram",
      min_gram: "3",
      max_gram: "10",
      token_chars: %w[letter digit]
    }
  } 
}

您可以使用映射中的 multi_field 以多种方式为同一字段编制索引。您可以在默认字段上使用带有自定义分词器的全文搜索,并为您的自动完成需求创建一个特殊的索引。

"title": {
    "type": "string",
    "fields": {
        "raw":   { "type": "string", "index": "not_analyzed" }
    }
}

执行自动完成时,您的查询需要略有不同,因为字段将是 title.raw 而不是 title.

一旦字段以对您的查询有意义的所有方式编入索引,您就可以使用布尔 "should" 查询来查询索引,匹配标记化版本和单词开始查询。很可能应该为第一个匹配完整单词的查询提供更大的提升,以获得顶部的直接命中。