Вам необходимо создать отображение, как показано ниже
PUT index38
{
"mappings": {
"properties": {
"title": {
"type": "text", ----> for searching
"analyzer": "autocomplete_analyzer",
"fields": {
"keyword": {
"type": "keyword" --- > for terms aggregation
}
}
}
}
},
"settings": {
"analysis": {
"filter": {
"autocomplete_filter": {
"type": "edge_ngram",
"min_gram": 3,
"max_gram": 20
}
},
"analyzer": {
"autocomplete_analyzer": {
"tokenizer": "autocomplete_tokenizer",
"filter": [
"lowercase",
"autocomplete_filter"
]
}
},
"tokenizer": {
"autocomplete_tokenizer": {
"type": "edge_ngram",
"min_gram": 2,
"max_gram": 20,
"token_chars": [
"letter"
]
}
}
}
}
}
В агрегации приходит несколько токенов из-за установки fielddata как true
Из документов
поле текста анализируется до индексации, так что значение, как Нью-Йорк, можно найти с помощью поиска новых или для йорка. А условия агрегации на этом поле будет возвращать новое ведро и йорк ведро, когда вы, вероятно, хотите, один ковш под названием Нью-Йорк. Вместо этого у вас должно быть текстовое поле для полнотекстового поиска и неанализированное поле ключевого слова с включенными значениями doc_values для агрегатов
Необходимо создать подполе с именем ключевого слова с типом keyword ,который хранит весь текст в виде одного токена.
Edit1: Mapping
GET index38/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"title": {
"query": "Zahnar",
"analyzer": "autocomplete_analyzer"
}
}
}
]
}
},
"aggs": {
"autocomplete": {
"terms": {
"field": "title.keyword",
"include": "zahnar.*",
"order": {
"_count": "desc"
}
}
}
}
}
Данные:
[
{
"_index" : "index38",
"_type" : "_doc",
"_id" : "ilUK_G0Bl2iO22h0waYm",
"_score" : 1.0,
"_source" : {
"title" : "Zahnarzt"
}
},
{
"_index" : "index38",
"_type" : "_doc",
"_id" : "i1UK_G0Bl2iO22h0xabf",
"_score" : 1.0,
"_source" : {
"title" : "zahnarztpraxis"
}
},
{
"_index" : "index38",
"_type" : "_doc",
"_id" : "jFUK_G0Bl2iO22h0zabu",
"_score" : 1.0,
"_source" : {
"title" : "zahnarztpraxen"
}
},
{
"_index" : "index38",
"_type" : "_doc",
"_id" : "jVUK_G0Bl2iO22h00qYI",
"_score" : 1.0,
"_source" : {
"title" : "Zahnarzt abc"
}
}
]
Запрос:
GET index38/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"title": {
"query": "Zahnar",
"analyzer": "autocomplete_analyzer"
}
}
}
]
}
},
"aggs": {
"autocomplete": {
"terms": {
"field": "title.keyword",
"include": "zahnar.*",
"order": {
"_count": "desc"
}
}
}
}
}
Ответ:
[
{
"_index" : "index38",
"_type" : "_doc",
"_id" : "i1UK_G0Bl2iO22h0xabf",
"_score" : 0.90610546,
"_source" : {
"title" : "zahnarztpraxis"
}
},
{
"_index" : "index38",
"_type" : "_doc",
"_id" : "jFUK_G0Bl2iO22h0zabu",
"_score" : 0.90610546,
"_source" : {
"title" : "zahnarztpraxen"
}
},
{
"_index" : "index38",
"_type" : "_doc",
"_id" : "ilUK_G0Bl2iO22h0waYm",
"_score" : 0.8928052,
"_source" : {
"title" : "Zahnarzt"
}
},
{
"_index" : "index38",
"_type" : "_doc",
"_id" : "jVUK_G0Bl2iO22h00qYI",
"_score" : 0.8913534,
"_source" : {
"title" : "Zahnarzt abc"
}
}
]
},
"aggregations" : {
"autocomplete" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "zahnarzt",
"doc_count" : 2
},
{
"key" : "zahnarztpraxen",
"doc_count" : 1
},
{
"key" : "zahnarztpraxis",
"doc_count" : 1
}
]
}
}
Есть и другой вариант, если вы не используете autocomplete_analyzer
GET index38/_search
{
"query": {
"bool": {
"must": [
{
"match_phrase_prefix": {
"title": {
"query": "zahn"
}
}
}
]
}
},
"highlight" : {
"fields" : {
"title" : {}
}
}
}
Вам нужно будет получить токены из выделенных полей на стороне клиента. и матч фраза будет соответствовать тексту в любом месте и не подходят для автозаполнения типа функциональных