【问题标题】:ElasticSearch: exact has lower score than partial matchElasticSearch:精确的分数低于部分匹配
【发布时间】:2016-06-23 16:02:57
【问题描述】:

我正在尝试使用 ElasticSearch 实现地址自动完成。

假设,我想在三个字段上实现搜索:

{
    "address_name": "George st.",
    "number": "1",
    "city_name": "London"
}

根据this article,我已经像这样配置了我的索引和类型:

{
    "settings": {
        "analysis": {
            "filter": {
                "nGram_filter": {
                    "type": "nGram",
                    "min_gram": 1,
                    "max_gram": 20,
                    "token_chars": [
                        "letter",
                        "digit",
                        "punctuation",
                        "symbol"
                    ]
                }
            },
            "analyzer": {
                "nGram_analyzer": {
                    "type": "custom",
                    "tokenizer": "whitespace",
                    "filter": [
                        "lowercase",
                        "asciifolding",
                        "nGram_filter"
                    ]
                },
                "whitespace_analyzer": {
                    "type": "custom",
                    "tokenizer": "whitespace",
                    "filter": [
                        "lowercase",
                        "asciifolding"
                    ]
                }
            }
        }
    },
    "mappings": {
        "address": {
            "_all": {
                "analyzer": "nGram_analyzer",
                "search_analyzer": "whitespace_analyzer"
            },
            "properties": {
                "address_name": {
                    "type": "string"
                },
                "number": {
                    "type": "string",
                    "boost": 2
                },
                "city_name": {
                    "type": "string"
                },
                "local": {
                    "type": "integer",
                    "include_in_all": false,
                    "index": "no"
                },
                "place_id": {
                    "type": "integer",
                    "include_in_all": false,
                    "index": "no"
                },
                "has_number": {
                    "type": "integer",
                    "include_in_all": false,
                    "index": "no"
                }
            }
        }
    }
}

完整的搜索查询:

{
    "size": 100,
    "query": {
        "match": {
            "_all": {
                "query": "George st. 1 London",
                "operator": "and"
            }
        }
    }
}

当我通过查询 George st. 1 London 进行搜索时,ElasticSearch 首先返回我 George st. 19 LondonGeorge st. 17 London 等,但精确匹配 George st. 1 London 仅在第 X 位返回,并且得分低于第一个。

我试图通过在搜索 URL 的末尾添加 explain 查询来了解为什么会发生这种情况,但它没有帮助。

有没有办法解决这个问题?

谢谢。

【问题讨论】:

  • 您也可以分享您发送的查询吗?
  • George st. 1 London。谢谢。
  • 我的意思是您使用的是什么查询 DSL?您能说明您是如何发送查询的吗?
  • 哦,是的,当然:{ "size": 100, "query": { "match": { "_all": { "query": "George st. 1 London", "operator": "and" } } } }

标签: json elasticsearch autocomplete


【解决方案1】:

基本上,由于您在索引时通过 nGram 令牌过滤器运行所有字段,这意味着对于 number 字段,

  • 17 将被标记为 117
  • 19 将被标记为 119

因此,您提到的所有三个文档都将为其number 字段索引标记1

然后在查询时,您正在使用空格分析器,这意味着 George st. 1 London 将被标记为以下标记:Georgest1London

由此,我们可以得出两个结论:

  1. 无论如何,所有三个文档都将匹配(因为所有标记都匹配给定字段)
  2. 使用当前设置和映射,您无法赋予文档George st. 1 London 比其他文档更大的权重。

解决此问题的最简单方法是不将 nGram 应用于号码字段,以便街道号码需要完全匹配而不是前缀。

【讨论】:

  • 您是否只需将数字字段设置为 not_analyzed?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-12
  • 2019-04-03
  • 2014-08-12
  • 1970-01-01
  • 1970-01-01
  • 2023-03-24
  • 2023-03-30
相关资源
最近更新 更多