Возможное решение этой проблемы - использовать мультиполя . Они позволяют по-разному индексировать одни и те же данные из исходного документа. В вашем случае вы можете индексировать поле name
по умолчанию text
, затем как ngrams
, а также как edgengrams . Тогда запрос должен быть bool запрос по сравнению со всеми этими 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"
}
}
}
]
}
}
}