我正在尝试使用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 London
,George st. 17 London
等,但是完全匹配的George st. 1 London
仅在第X个位置返回,并且得分比第一个低。我试图通过在搜索URL的末尾添加
explain
查询来了解为什么会发生这种情况,但这没有帮助。有什么办法解决这个问题?
谢谢。
最佳答案
基本上,由于您是在建立索引时通过nGram token 过滤器运行所有字段,因此对于number
字段,
17
将标记为1
和17
和19
将标记为1
和19
因此,您提到的所有三个文档都将为其
1
字段索引标记number
。然后在查询时,您将使用空白分析器,这意味着
George st. 1 London
将被标记为以下标记:George
,st
,1
和London
。从那里,我们可以得出两个结论:
George st. 1 London
比其他文件赋予更多权重。 解决此问题的最简单方法是不将nGram应用于数字字段,以便街道编号需要准确匹配且不带前缀。
关于json - ElasticSearch:完全比部分匹配的得分低,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35888896/