Настройка Elasticsearch для автодополнения (Completion Suggester)
Автодополнение в поиске — это не просто «найти по префиксу». Пользователь вводит «но» и ожидает «ноутбук», «носки», «ноябрь» — мгновенно, без задержки. Elasticsearch предоставляет два механизма: Completion Suggester (специализированная in-memory структура) и Edge N-gram (стандартный поиск по частичному токену). Выбор зависит от требований к скорости, гибкости запросов и объёма данных.
Completion Suggester
Completion Suggester хранит данные в специальной FST (Finite State Transducer) структуре в памяти. Это самый быстрый вариант автодополнения — ответ за 1–5 мс. Но он менее гибкий: нет полнотекстового скоринга, ограниченные возможности фильтрации.
Маппинг для поля типа completion:
PUT /products
{
"mappings": {
"properties": {
"title": {
"type": "text"
},
"suggest": {
"type": "completion",
"analyzer": "simple",
"search_analyzer": "simple",
"preserve_separators": true,
"preserve_position_increments": true,
"max_input_length": 50
}
}
}
}
Индексация документа с suggest-полем:
PUT /products/_doc/1
{
"title": "Ноутбук ASUS VivoBook 15",
"suggest": {
"input": [
"Ноутбук ASUS VivoBook",
"ASUS VivoBook 15",
"VivoBook"
],
"weight": 10
}
}
Поле input — список вариантов, с которых начинается автодополнение. weight — приоритет в выдаче (выше = первее). Для популярных товаров ставьте вес на основе продаж или кликов.
Запрос автодополнения:
POST /products/_search
{
"suggest": {
"product-suggest": {
"prefix": "ноут",
"completion": {
"field": "suggest",
"size": 5,
"skip_duplicates": true,
"fuzzy": {
"fuzziness": 1
}
}
}
},
"_source": ["title", "price"],
"size": 0
}
size: 0 в основном запросе — не возвращаем обычные результаты поиска, только саджесты. fuzzy.fuzziness: 1 — допускает одну опечатку в префиксе.
Ответ:
{
"suggest": {
"product-suggest": [{
"text": "ноут",
"offset": 0,
"length": 4,
"options": [
{
"text": "Ноутбук ASUS VivoBook",
"_score": 10,
"_source": { "title": "Ноутбук ASUS VivoBook 15", "price": 49900 }
}
]
}]
}
}
Context Suggester — фильтрация саджестов
Если нужно ограничить автодополнение по категории или другому атрибуту — используйте Context Suggester:
PUT /products
{
"mappings": {
"properties": {
"suggest": {
"type": "completion",
"contexts": [
{
"name": "category",
"type": "category",
"path": "category"
}
]
},
"category": { "type": "keyword" }
}
}
}
Индексация:
PUT /products/_doc/1
{
"title": "Ноутбук ASUS",
"category": "laptops",
"suggest": {
"input": ["Ноутбук ASUS", "ASUS"],
"contexts": {
"category": ["laptops"]
}
}
}
Запрос с контекстом:
POST /products/_search
{
"suggest": {
"product-suggest": {
"prefix": "ас",
"completion": {
"field": "suggest",
"size": 5,
"contexts": {
"category": [
{ "context": "laptops", "boost": 2 },
{ "context": "tablets" }
]
}
}
}
}
}
Edge N-gram как альтернатива
Edge N-gram индексирует частичные токены: «но», «ноу», «ноут», «ноутб» и т.д. Позволяет использовать стандартный match запрос, полный скоринг TF/IDF, фильтрацию и сортировку.
PUT /products
{
"settings": {
"analysis": {
"tokenizer": {
"edge_ngram_tokenizer": {
"type": "edge_ngram",
"min_gram": 2,
"max_gram": 20,
"token_chars": ["letter", "digit"]
}
},
"analyzer": {
"autocomplete_index": {
"type": "custom",
"tokenizer": "edge_ngram_tokenizer",
"filter": ["lowercase"]
},
"autocomplete_search": {
"type": "custom",
"tokenizer": "standard",
"filter": ["lowercase"]
}
}
}
},
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "autocomplete_index",
"search_analyzer": "autocomplete_search"
}
}
}
}
Запрос:
POST /products/_search
{
"query": {
"match": {
"title": {
"query": "ноут",
"operator": "and"
}
}
},
"sort": [{ "_score": "desc" }],
"size": 5
}
Когда что использовать
Completion Suggester — когда нужна максимальная скорость (<5 мс), источник данных ограничен (каталог товаров, список городов, имена пользователей), веса рассчитываются заранее.
Edge N-gram — когда нужна полноценная фильтрация по атрибутам вместе с автодополнением, сортировка по релевантности с учётом TF/IDF, поиск в середине строки (N-gram без edge).
Реализация на стороне приложения
PHP пример с Laravel и elastic/elasticsearch-php:
public function autocomplete(string $query): array
{
$response = $this->client->search([
'index' => 'products',
'body' => [
'suggest' => [
'product-suggest' => [
'prefix' => mb_strtolower($query),
'completion' => [
'field' => 'suggest',
'size' => 8,
'skip_duplicates' => true,
'fuzzy' => ['fuzziness' => 'AUTO'],
]
]
],
'_source' => ['title', 'slug', 'price'],
'size' => 0,
]
]);
$options = $response['suggest']['product-suggest'][0]['options'] ?? [];
return array_map(fn($opt) => [
'title' => $opt['text'],
'url' => '/products/' . $opt['_source']['slug'],
'price' => $opt['_source']['price'],
], $options);
}
На фронтенде — debounce на 200–300 мс перед запросом, чтобы не отправлять запрос на каждый символ.
Сроки
Настройка Completion Suggester с популяризацией по весам — 1 рабочий день. Добавление Context Suggester с фильтрацией по категориям — ещё полдня. Edge N-gram с полноценной интеграцией в поиск — 1–2 дня.







