假设Edge NGram令牌生成器具有以下映射:
{
"settings": {
"analysis": {
"analyzer": {
"autocomplete_analyzer": {
"tokenizer": "autocomplete_tokenizer",
"filter": [
"standard"
]
},
"autocomplete_search": {
"tokenizer": "whitespace"
}
},
"tokenizer": {
"autocomplete_tokenizer": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 10,
"token_chars": [
"letter",
"symbol"
]
}
}
}
},
"mappings": {
"tag": {
"properties": {
"id": {
"type": "long"
},
"name": {
"type": "text",
"analyzer": "autocomplete_analyzer",
"search_analyzer": "autocomplete_search"
}
}
}
}
}
并为以下文档建立索引:
POST /tag/tag/_bulk
{"index":{}}
{"name" : "HITS FIND SOME"}
{"index":{}}
{"name" : "TRENDING HI"}
{"index":{}}
{"name" : "HITS OTHER"}
然后搜索
{
"query": {
"match": {
"name": {
"query": "HI"
}
}
}
}
产生的所有分数相同,或TRENDING - HI
的得分高于其他得分。
如何配置它以更高的分数显示实际以搜索者n-gram开头的条目?在这种情况下,HITS FIND SOME
和HITS OTHER
的得分要高于TRENDING HI
;同时TRENDING HI
应该出现在结果中。
还使用了Highlighter,因此给定的解决方案不应该弄乱它。
查询中使用的荧光笔是:
"highlight": {
"pre_tags": [
"<"
],
"post_tags": [
">"
],
"fields": {
"name": {}
}
}
将其与match_phrase_prefix
配合使用会弄乱突出显示,仅搜索<H><I><T><S> FIND SOME
时会产生H
。
答案 0 :(得分:4)
您必须了解elasticsearch / lucene如何分析您的数据并计算搜索得分。
1。分析API
https://www.elastic.co/guide/en/elasticsearch/reference/current/_testing_analyzers.html,这将显示您所用的Elasticsearch存储的内容:
T / TR / TRE /.... TRENDING / / H / HI
2。得分
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html
布尔查询通常用于在需要特定用例的情况下构建复杂的查询。使用must
过滤文档,然后使用should
进行评分。一个常见的用例是在同一字段上使用不同的分析器(通过在映射中使用关键字fields
,您可以不同地分析同一字段)。
3。不要混乱突出显示
您可以添加一个额外的查询:
{
"query": {
"bool": {
"must" : [
{
"match": {
"name": "HI"
}
}
],
"should": [
{
"prefix": {
"name": "HI"
}
}
]
}
},
"highlight": {
"pre_tags": [
"<"
],
"post_tags": [
">"
],
"fields": {
"name": {
"highlight_query": {
"match": {
"name": "HI"
}
}
}
}
}
}
答案 1 :(得分:3)
在这种特殊情况下,您可以向查询中添加一个match_phrase_prefix
词,该词在文本的最后一个词上没有前缀匹配:
{
"query": {
"bool": {
"should": [
{
"match": {
"name": "HI"
}
},
{
"match_phrase_prefix": {
"name": "HI"
}
}
]
}
}
}
match
项将在所有三个结果上都匹配,但match_phrase_prefix
在TRENDING HI
上将不匹配。结果,您将获得结果中的所有三个项目,但是TRENDING HI
的得分会降低。
引用docs:
match_phrase_prefix查询是穷人的自动完成[...]有关按类型搜索的更好解决方案,请参见完成建议器和“按时间搜索按类型搜索”。
顺便说一句,如果要引入bool
查询,则可能要根据所需结果查看minimum_should_match
选项。
答案 2 :(得分:1)
此问题的可能解决方案是使用multifields。它们允许以不同的方式索引源文档中的相同数据。在您的情况下,您可以将name
字段索引为默认text
,然后索引为ngrams
,也索引为edgengrams。然后,查询将必须是bool query与所有这些不同的fields
进行比较。
文件的最终分数由每个文件的匹配值组成。这些匹配也称为signals
,表示查询和文档之间存在匹配。信号匹配程度最高的文档得分最高。
在您的情况下,所有文档都将与ngram
HI
相匹配。但是只有HITS FIND SOME
和HITS OTHER
文档会获得edgengram
的额外分数。这将使这两个文档得到提升,并将它们放在首位。这样做的麻烦之处在于,您必须确保edgengram
不会在空格上分割,因为这样末尾的HI
将获得与文档开头相同的分数。
以下是针对您的案例的映射和查询示例:
PUT /tag/
{
"settings": {
"analysis": {
"analyzer": {
"edge_analyzer": {
"tokenizer": "edge_tokenizer"
},
"kw_analyzer": {
"tokenizer": "kw_tokenizer"
},
"ngram_analyzer": {
"tokenizer": "ngram_tokenizer"
},
"autocomplete_analyzer": {
"tokenizer": "autocomplete_tokenizer",
"filter": [
"standard"
]
},
"autocomplete_search": {
"tokenizer": "whitespace"
}
},
"tokenizer": {
"kw_tokenizer": {
"type": "keyword"
},
"edge_tokenizer": {
"type": "edge_ngram",
"min_gram": 2,
"max_gram": 10
},
"ngram_tokenizer": {
"type": "ngram",
"min_gram": 2,
"max_gram": 10,
"token_chars": [
"letter",
"digit"
]
},
"autocomplete_tokenizer": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 10,
"token_chars": [
"letter",
"symbol"
]
}
}
}
},
"mappings": {
"tag": {
"properties": {
"id": {
"type": "long"
},
"name": {
"type": "text",
"fields": {
"edge": {
"type": "text",
"analyzer": "edge_analyzer"
},
"ngram": {
"type": "text",
"analyzer": "ngram_analyzer"
}
}
}
}
}
}
}
和查询:
POST /tag/_search
{
"query": {
"bool": {
"should": [
{
"function_score": {
"query": {
"match": {
"name.edge": {
"query": "HI"
}
}
},
"boost": "5",
"boost_mode": "multiply"
}
},
{
"match": {
"name.ngram": {
"query": "HI"
}
}
},
{
"match": {
"name": {
"query": "HI"
}
}
}
]
}
}
}