9

是否可以告诉 ElasticSearch 使用所有克的“最佳匹配”而不是使用克作为同义词?

默认情况下,ElasticSearch 使用grams 作为同义词并返回匹配不佳的文档。最好用例子来展示,假设我们有两个人在索引中:

alice wang
sarah kerry

我们搜索ali12345

{
  query: {
    bool: {
      should: {
        match: { name: 'ali12345' }
      }
    }
  }
}

它会返回alice wang

这怎么可能?因为默认情况下 ElasticSearch 使用grams 作为同义词,所以,即使只有一个gram 匹配 - 文档也会被匹配

如果您检查查询,您会看到它将克视为同义词

...
"explanation": {
  "value": 5.274891,
  "description": "weight(Synonym(name: ali name:li1 name:i12 name:123 name:234 name:345 ) in 0) [PerFieldSimilarity], result of:",
...

我想知道是否可以告诉它使用“最佳匹配”查询,以实现类似:

{
  query: {
    bool: {
      should: [
        { term: { body: 'ali' }},
        { term: { body: 'li1' }},
        { term: { body: 'i12' }},
        { term: { body: '123' }},
        { term: { body: '234' }},
        { term: { body: '345' }},
      ],
      minimum_should_match: '75%'
    }
  }
}

问题:

  1. 当然可以手动生成此查询,但是您必须手动应用 ngram 解析和其他分析器管道。所以我想知道它是否可以由 ElasticSearch 完成

  2. 当有几十克/术语时,这种长字符串查询的性能是什么?它是否会使用一些智能优化,例如搜索类似文档(请参阅more_like_this) - 当它尝试不使用所有术语而只使用最高的术语时tf-idf

附言

指标配置

{
  mappings: {
    object: {
      properties: {
        name: {
          type:     'text',
          analyzer: 'trigram_analyzer'
        }
      }
    }
  },

  settings: {
    analysis: {
      filter: {
        trigram_filter: { type: 'ngram', min_gram: 3, max_gram: 3 }
      },
      analyzer: {
        trigram_analyzer: {
          type:        'custom',
          tokenizer:   'keyword',
          filter:      [ 'trigram_filter' ]
        }
      }
    }
  }
}
4

2 回答 2

1

也许您已经找到了原因,但是ali12345匹配alice wang是因为搜索时的分析器与用于索引时间的分析器相同,包括 ngram。

这样:

在索引时间:对于 text alice wang,这些术语被创建 [ ali, lic, ice, ...]

在搜索时:对于 text ali12345,这些术语被创建 [ ali, li1, i12, ...]

如我们所见,我们与 term 匹配ali

为了避免这个问题,ElasticSearch 提供了为搜索时间指定不同分析器的可能性。在字段的映射中,name您可以添加另一个search_analyzer通常与 main 非常相似analyzer但没有 ngram 标记过滤器的属性。这将防止在搜索分析期间生成 [ ali, li1, i12] 导致 0 匹配到alice wang

随意查看此页面上的更多详细信息和解释:https ://www.elastic.co/guide/en/elasticsearch/reference/current/search-analyzer.html

于 2020-10-02T17:19:21.230 回答
1

我知道这个问题很老,但以防万一......

您应该能够在 trigram 查询中使用 minimumShouldMatch 子句来指定必须匹配多少 trigram 才能将记录视为命中。您可以使用“3<75%”之类的内容,这意味着“如果有 3 个或更少的三元组,则 100% 必须匹配。是否有 4 个或更多的三元组,则 75% 必须匹配”

于 2019-10-28T08:19:01.657 回答