【问题标题】:Elasticsearch: Unexpected interaction between synonym_graph and stop filter in custom analyzerElasticsearch:自定义分析器中 synonym_graph 和停止过滤器之间的意外交互
【发布时间】:2021-07-04 03:06:59
【问题描述】:

说明

我正在尝试使用包括停用词在内的多词同义词进行查询。 我们先举个例子来说明。

我已将以下文档放入索引中。

  • 酒吧
  • 富吧
  • 酒吧的富人
  • 脸书

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

  • 富吧
  • 酒吧的富人
  • 脸书

配置

在这个例子中,我有 2 个过滤器:

  • stop:将移除标记 of
  • synonym_graph:处理同义词fb、foo bar、foo of bar

映射

{
  "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 格式:"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

所有搜索都期望返回 3 行:

  • 脸书
  • 富吧
  • 酒吧的富人

注意:bar 的 foo 永远不会返回

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

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

【问题讨论】:

标签: elasticsearch filter stop-words synonym


【解决方案1】:

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

{
  "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”标记位于 0 的位置,“bar”位于 2 的位置,因此同义词过滤器无法找到此文档。

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

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

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

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

【讨论】:

  • 同义词 "fb,foo bar,foo of bar" 并在末尾添加停止过滤器会给出以下结果:- 搜索 "foo of bar" 返回文档 "fb","foo bar" -搜索“fb”返回文档“fb”、“foo bar” - 仅搜索“foo bar”返回文档“fb”
  • 感谢您的链接,如果它从 elasticsearch 7.3 版开始被弃用,我将深入研究“常用术语查询”事件?
  • 有关信息,删除停用词过滤器并使用同义词“fb,foo bar,foo of bar”返回预期内容。但我们需要使用真实数据集检查调整回归以及性能影响。
  • @Joan,我认为匹配查询将与基于使用 BM25 Similarity 的“常用术语查询”相同。有关 BM25 的更多信息,请查看en.wikipedia.org/wiki/Okapi_BM25
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-04
  • 1970-01-01
  • 2018-10-05
  • 2020-12-27
  • 2016-09-25
  • 2014-08-08
  • 1970-01-01
相关资源
最近更新 更多