弹性搜索中的自动完成匹配
Autocomplete matching in Elastic Search
所以我在弹性搜索中有一个 identifier
字符串字段,其中包含 D123
、M1
、T23
等值
我正在尝试在该字段的搜索中构建自动完成功能,以便 D12
的查询可能匹配 D12
、D120
、D121
、... , D1210
等
目前我已经构建了一个自定义的边缘 ngram 过滤器和分析器:
"filter": {
"autocomplete_filter": {
"type": "edgeNGram",
"min_gram": 2,
"max_gram": 10
}
}
"analyzer": {
"autocomplete": {
"type": "custom",
"tokenizer": "whitespace",
"filter": {"lowercase", "autocomplete_filter"}
}
}
在我的映射中,当 indexing:
时,我在 identifier
字段上使用它
"identifier": {
"type": "string",
"analyzer": "autocomplete",
"search_analyzer": "standard"
}
这意味着为 D1234
编制索引的 ngram 是 D1
、D12
、D123
和 D1234
。
要查询这个我是这样做的:
"query": {
"bool": {
"should": {
"match": {
"identifier": {
"query": "D12",
"fuzziness": 0
}
}
}
}
}
这个returns结果从最长到最短,所以D12
出现在结果的末尾。我将如何确保尽可能短的标识符具有最高的相关性分数?
我的猜测是 D12
查询像这样匹配 ngrams:[{D12}, {D12}3, {D12}34]
并且弹性搜索去 "Oh great, 3 matches!" 而不是 [{D12}]
D12
结果会给出。
我想一个解决方案可能不会部分匹配那些 ngram,因此弹性搜索会看到两个结果的 [{D12}]
但排名 D12
高于 D1234
因为它匹配了 1/2 ngram 而不是 1/4。我不确定如何配置弹性搜索来给出这个结果。
如有任何帮助,我们将不胜感激。
您可以使用 script based sorting 执行此操作,但首先您需要将 identifier
字段映射为 multi-fields
,就像这样
"identifier": {
"type": "string",
"analyzer": "autocomplete",
"search_analyzer": "standard",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
}
}
}
您需要这样做,因为如果您直接在 identifier
上 sort
那么您将得到相同的结果,因为它们都将具有 2 个字母标记 由于 edge ngram filter
。之后这会给你想要的结果
{
"query": {
"bool": {
"should": {
"match": {
"identifier": {
"query": "D12",
"fuzziness": 0
}
}
}
}
},
"sort": {
"_script": {
"script": "doc['identifier.raw'].value.length()",
"order": "asc",
"type": "number"
}
}
}
希望对您有所帮助!!
所以我在弹性搜索中有一个 identifier
字符串字段,其中包含 D123
、M1
、T23
等值
我正在尝试在该字段的搜索中构建自动完成功能,以便 D12
的查询可能匹配 D12
、D120
、D121
、... , D1210
等
目前我已经构建了一个自定义的边缘 ngram 过滤器和分析器:
"filter": {
"autocomplete_filter": {
"type": "edgeNGram",
"min_gram": 2,
"max_gram": 10
}
}
"analyzer": {
"autocomplete": {
"type": "custom",
"tokenizer": "whitespace",
"filter": {"lowercase", "autocomplete_filter"}
}
}
在我的映射中,当 indexing:
时,我在identifier
字段上使用它
"identifier": {
"type": "string",
"analyzer": "autocomplete",
"search_analyzer": "standard"
}
这意味着为 D1234
编制索引的 ngram 是 D1
、D12
、D123
和 D1234
。
要查询这个我是这样做的:
"query": {
"bool": {
"should": {
"match": {
"identifier": {
"query": "D12",
"fuzziness": 0
}
}
}
}
}
这个returns结果从最长到最短,所以D12
出现在结果的末尾。我将如何确保尽可能短的标识符具有最高的相关性分数?
我的猜测是 D12
查询像这样匹配 ngrams:[{D12}, {D12}3, {D12}34]
并且弹性搜索去 "Oh great, 3 matches!" 而不是 [{D12}]
D12
结果会给出。
我想一个解决方案可能不会部分匹配那些 ngram,因此弹性搜索会看到两个结果的 [{D12}]
但排名 D12
高于 D1234
因为它匹配了 1/2 ngram 而不是 1/4。我不确定如何配置弹性搜索来给出这个结果。
如有任何帮助,我们将不胜感激。
您可以使用 script based sorting 执行此操作,但首先您需要将 identifier
字段映射为 multi-fields
,就像这样
"identifier": {
"type": "string",
"analyzer": "autocomplete",
"search_analyzer": "standard",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
}
}
}
您需要这样做,因为如果您直接在 identifier
上 sort
那么您将得到相同的结果,因为它们都将具有 2 个字母标记 由于 edge ngram filter
。之后这会给你想要的结果
{
"query": {
"bool": {
"should": {
"match": {
"identifier": {
"query": "D12",
"fuzziness": 0
}
}
}
}
},
"sort": {
"_script": {
"script": "doc['identifier.raw'].value.length()",
"order": "asc",
"type": "number"
}
}
}
希望对您有所帮助!!