首页 > 解决方案 > 如何使用elasticsearch正确处理多词同义词扩展?

问题描述

我有以下同义词扩展:

suco => suco, refresco, bebida de soja

我想要的是以这种方式标记搜索:

搜索“suco de laranja”将被标记为 [“suco”、“laranja”、“refresco”、“bebida de soja”]。

但我将其标记为 [“suco”、“laranja”、“refresco”、“bebida”、“soja”]。

考虑“ de ”字是停用词。我希望它在查询中被忽略,例如“bebida de laranja”变成[“bebida”,“laranja”]。但我不希望在同义词标记化中考虑它,因此“bebida de soja”仍然作为一个标记“bebida de soja”。

我的设置 :

{
    "settings":{
        "analysis":{
            "filter":{
                "synonym_br":{
                    "type":"synonym",
                    "synonyms":[
                        "suco => suco, refresco, bebida de soja"
                    ]
                },
                "brazilian_stop":{
                    "type":"stop",
                    "stopwords":"_brazilian_"
                }
            },
            "analyzer":{
                "synonyms":{
                    "filter":[
                        "synonym_br",
                        "lowercase",
                        "brazilian_stop",
                        "asciifolding"
                    ],
                    "type":"custom",
                    "tokenizer":"standard"
                }
            }
        }
    }
}

标签: elasticsearchelastic-stackelasticsearch-5

解决方案


我建议您进行以下两项更改。第一个与您提出的问题直接相关,第二个是建议。

  1. 不要使用多个同义词的扩展,而是做相反的事情,即所有同义词都指向一个单词同义词。所以,"suco => suco, refresco, bebida de soja"改为"suco, refresco, bebida de soja => suco"

  2. 更改synonyms分析器中过滤器的顺序。放在lowercase前面synonym_br。这将确保这种情况不会影响synonym_br令牌过滤器。

所以最终设置将是:

{
  "settings": {
    "analysis": {
      "filter": {
        "synonym_br": {
          "type": "synonym",
          "synonyms": [
            "suco, refresco, bebida de soja => suco"
          ]
        },
        "brazilian_stop": {
          "type": "stop",
          "stopwords": "_brazilian_"
        }
      },
      "analyzer": {
        "synonyms": {
          "filter": [
            "lowercase",
            "synonym_br",
            "brazilian_stop",
            "asciifolding"
          ],
          "type": "custom",
          "tokenizer": "standard"
        }
      }
    }
  }
}

这是如何运作的?

对于输入bebida de soja过滤器,按以下顺序应用:

Input Filter        Result tokens
====================================
lowercase           bebida, de, soja
synonym_br          suco             <------- all the above tokens(including position) exactly matches a synonym
brazilian_stop      suco
asciifolding        suco

让我们看看brazilian_stop实际情况。为此,我们需要一个与同义词不匹配但包含de在其中的输入。例如de soja

Input Filter        Result tokens
=================================
lowercase           de, soja
synonym_br          de, soja  <------- none of the tokens (independently or combined(including position)) matches any synonym
brazilian_stop      soja      <------- de is removed as it is a stopword
asciifolding        soja

推荐阅读