Elasticsearch:synonym_graph 与自定义分析器中的停止过滤器之间的意外交互

Elasticsearch: Unexpected interaction between synonym_graph and stop filter in custom analyzer

描述

我正在尝试使用包含停用词的多词同义词进行查询。 先举个例子来解释一下吧。

我已将以下文档编入索引。

查询 {"query":{"match":{"test":{"query":"foo of bar"}}}} 的预期结果是 return 文档:

配置

在这个例子中,我得到了 2 个过滤器:

映射

{
  "properties": {
    "test": {
      "type": "text",
      "analyzer": "test_index_analyzer",
      "search_analyzer": "test_search_analyzer"
    }
}

设置

{
    "settings" : {
        "index": {
            "number_of_shards": 1,
            "number_of_replicas": 0,
            "analysis": {
                "analyzer": {
                    "test_index_analyzer": {
                        "type": "custom",
                        "tokenizer": "whitespace",
                        "filter": [
                            "english_stop"
                        ]
                    },
                    "test_search_analyzer": {
                        "type": "custom",
                        "tokenizer": "whitespace",
                        "filter": [
                            "english_stop",
                            "english_syn"
                        ]
                    }
                },
                "filter": { 
                    "english_stop": {
                        "type": "stop",
                        "stopwords": "_english_",
                        "ignore_case": true,
                        "remove_trailing": false
                    },
                    "english_syn": {
                        "type": "synonym_graph",
                        "synonyms": [
                            "fb,foo of bar",
                            "fb,foo bar"
                        ]
                    }
                }
            }
        }
    }
}

结果

token format: "token,start_offset-end_offset,type / position / positionLength"

Query Search Result index analysys Search analysys
fb fb fb,0-2,word,0,1 foo,0-2,SYNONYM / 0 / 1
foo,0-2,SYNONYM / 0 / 3
fb,0-2,word / 0 / 4
bar,0-2,SYNONYM / 2 / 2
bar,0-2,SYNONYM / 3 / 1
foo of bar fb foo,0-3,word,0,1
bar,7-10,word,2,1
fb,0-10,SYNONYM / 0 / 3
foo,0-3,word / 0 / 1
bar,7-10,word / 2 / 1
foo bar fb,foo bar foo,0-3,word,0,1
bar,4-7,word,1,1
fb,0-7,SYNONYM / 0 / 2
foo,0-3,word / 0 / 1
bar,4-7,word / 1 / 1

所有搜索都期望 return 3 行:

注意:bar 的 foo 永远不会 returned

我的猜测是 foo of bar 被停止过滤器索引到位置 [foo, ,bar] 并且同义词正在寻找 [foo, bar]。

你对实现我的目标有什么建议吗?

当您使用停用词过滤器时,单词的位置将被保留,因此如果您检查分析器结果中的 foo of bar,您将得到以下结果:

{
  "tokens" : [
    {
      "token" : "foo",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "bar",
      "start_offset" : 7,
      "end_offset" : 10,
      "type" : "word",
      "position" : 2
    }
  ]
}

如您所见,您在零位置获得 'foo' 令牌,在二位置获得 'bar',因此您的同义词过滤器无法找到该文档。

要解决您的问题,您应该首先应用同义词过滤器,然后删除停用词,如下所示。

"test_search_analyzer": {
    "type": "custom",
    "tokenizer": "whitespace",
    "filter": [
      "english_syn",
      "english_stop"
    ]
  }

您应该将 'foo bar, foo of bar' 添加到您的同义词列表中。

我认为保留停用词是必要的,因为它可以帮助获得更精确的搜索结果(尤其是与ES使用的BM25相似度。),您可以查看elasticsearch官方文章here