ElasticSearch使用ngram词项的“最佳匹配”而不是“同义词”?

9

能否告诉ElasticSearch使用所有字元的“最佳匹配”而非使用字元作为同义词?

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

alice wang
sarah kerry

我们正在搜索 ali12345:
{
  query: {
    bool: {
      should: {
        match: { name: 'ali12345' }
      }
    }
  }
}

它会返回alice wang,这是怎么做到的呢?因为ElasticSearch默认使用语法分词作为同义词,所以即使只有一个语法分词匹配上了,文档也可以被匹配

如果你检查查询语句,你会发现它把语法分词视为同义词。

...
"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值的术语而不是所有术语?

P.S.

索引配置

{
  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' ]
        }
      }
    }
  }
}

你实际上想要做什么?你目前使用的“match”查询方法有什么问题? - Andrei Stefan
@AndreiStefan 默认的“匹配”会将“alice wang”作为“ali12345”查询的匹配项。这显然是错误的。此外(虽然我不确定),相关性计算也以类似的错误方式进行。 - Alex Craft
它发现ali12345是因为ngrams。如果你不想让ali12345匹配,那么为什么要使用ngrams呢? - Andrei Stefan
它发现ali12345是因为ngrams。如果你不想让ali12345匹配,那么为什么要使用ngrams呢? - Andrei Stefan
你看过脚本相似性吗?https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-similarity.html#scripted_similarity 我不熟悉余弦相似度,需要花些时间去了解一下,但现在我没有时间。在这里指出脚本相似性,以防对你有所帮助。 - Andrei Stefan
显示剩余3条评论
2个回答

1
我知道这个问题很旧,但以防万一...
您应该能够在三元组查询中使用minimumShouldMatch子句来指定必须匹配多少个三元组才能将记录视为命中。您可以使用类似于“3<75%”的内容,表示“如果有3个或更少的三元组,则必须100%匹配。如果有4个或更多的三元组,则必须匹配75%”。

1
也许你已经找到了原因,但是ali12345alice wang匹配是因为在搜索时使用的分析器与索引时使用的相同,包括ngrams。
具体来说:
在索引时:对于文本alice wang,会创建这些术语[ali, lic, ice, ...]
在搜索时:对于文本ali12345,会创建这些术语[ali, li1, i12, ...]
正如我们所看到的,我们与术语ali匹配
为避免这个问题,ElasticSearch提供了在搜索时指定不同分析器的可能性。在字段name的映射中,可以添加另一个属性search_analyzer,通常与主要的analyzer非常相似,但没有ngram tokenfilter。这将防止在搜索分析期间生成[ali, li1, i12],从而导致与alice wang的0次匹配。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接