# Автозаполнение

Автозаполнение, или дополнение слов, предсказывает и предлагает окончание слова или фразы во время набора текста. Его обычно используют в:
- Поисковых строках на сайтах
- Подсказках в поисковых системах
- Текстовых полях в приложениях

Manticore предлагает продвинутую функцию автозаполнения, которая предлагает варианты во время ввода, подобно известным поисковым системам. Это помогает ускорить поиск и позволяет пользователям быстрее находить нужное.

Кроме базовой функции автозаполнения, Manticore включает расширенные возможности для улучшения пользовательского опыта:

1. **Коррекция орфографии (Fuzziness):** Автозаполнение Manticore помогает исправлять ошибки использования, используя алгоритмы, распознающие и исправляющие распространённые ошибки. Это значит, что даже если вы ввели что-то неправильно, вы всё равно сможете найти нужное.
2. **Автоматическое определение раскладки клавиатуры:** Manticore может определить, какую раскладку клавиатуры вы используете. Это особенно полезно в регионах с множеством языков или если вы случайно вводите текст на неправильном языке. Например, если вы ошибочно набрали «ghbdtn», Manticore понимает, что вы хотели написать «привет» и предлагает правильное слово.

Автозаполнение Manticore можно настроить под разные нужды и параметры, что делает его гибким инструментом для множества приложений.

![Автозаполнение](autocomplete.png)

## ВЫЗОВ AUTOCOMPLETE

> ПРИМЕЧАНИЕ: `CALL AUTOCOMPLETE` и `/autocomplete` требуют [Manticore Buddy](../Installation/Manticore_Buddy.md). Если не работает, убедитесь, что Buddy установлен.

<!-- example call_autocomplete -->
Для использования автозаполнения в Manticore используйте SQL-запрос `CALL AUTOCOMPLETE` или его JSON-эквивалент `/autocomplete`. Эта функция предлагает варианты дополнения слов на основе ваших индексированных данных.

Перед использованием убедитесь, что в таблице, которую вы планируете использовать для автозаполнения, включены [инфиксы](../Creating_a_table/NLP_and_tokenization/Wildcard_searching_settings.md#min_infix_len).

**Важно:** В настройках таблицы есть автоматическая проверка параметра `min_infix_len`, которая использует кэш на 30 секунд для повышения производительности `CALL AUTOCOMPLETE`. После изменения таблицы может быть небольшая задержка при первом вызове `CALL AUTOCOMPLETE` (обычно незаметная). В кэш сохраняются только успешные результаты, поэтому если вы удалите таблицу или отключите `min_infix_len`, `CALL AUTOCOMPLETE` временно может возвращать неверные результаты, пока не начнёт показывать ошибку, связанную с `min_infix_len`.

### Общий синтаксис

#### SQL
```sql
CALL AUTOCOMPLETE('query_beginning', 'table', [...options]);
```

#### JSON
```json
POST /autocomplete
{
	"table":"table_name",
	"query":"query_beginning"
	[,"options": {<autocomplete options>}]
}
```

#### Опции
- `layouts`: Строка, состоящая из кодов раскладок клавиатуры через запятую, для определения ошибок ввода, вызванных неправильной раскладкой (например, «ghbdtn» вместо «привет»). Manticore сравнивает позиции символов в разных раскладках, чтобы предлагать исправления. Для эффективного определения несоответствий нужны как минимум 2 раскладки. Доступные варианты: us, ru, ua, se, pt, no, it, gr, uk, fr, es, dk, de, ch, br, bg, be (подробнее [здесь](../Searching/Spell_correction.md#Options)). По умолчанию: none
- `fuzziness`: `0`, `1` или `2` (по умолчанию: `2`). Максимальное расстояние Левенштейна для поиска опечаток. Установите `0` для отключения нечёткого поиска
- `preserve`: `0` или `1` (по умолчанию: `0`). При значении `1` в результаты сохраняются слова без успешных нечётких совпадений (например, «hello wrld» вернёт «hello wrld» и «hello world»). При значении `0` возвращаются только слова с успешными нечёткими совпадениями (например, «hello wrld» вернёт только «hello world»). Особенно полезно для сохранения коротких слов или собственных имён, которые могут отсутствовать в Manticore Search
- `prepend`: Логическое (0/1 в SQL). Если true(1), добавляет звёздочку перед последним словом для префиксного расширения (например, `*word`)
- `append`: Логическое (0/1 в SQL). Если true(1), добавляет звёздочку после последнего слова для суффиксного расширения (например, `word*`)
- `expansion_len`: Количество символов для расширения последнего слова. По умолчанию: `10`
- `force_bigrams`: Логическое (0/1 в SQL). Принудительно использует биграммы (2-символьные n-граммы) вместо триграмм для всех длин слов, что может улучшить поиск для слов с ошибками перестановки символов. По умолчанию: `0` (используются триграммы для слов длиной ≥6 символов)

<!--
data for the following examples:

DROP TABLE IF EXISTS comment;
CREATE TABLE comment(content text) min_infix_len='2';
INSERT INTO comment(id,content) VALUES
(1,'hello'),
(2,'helio'),
(3,'hell'),
(4,'shell'),
(5,'nushell'),
(6,'powershell'),
(7,'well'),
(8,'help'),
(9,'hello world'),
(10,'hello wrld');

DROP TABLE IF EXISTS products;
CREATE TABLE products(name text) min_infix_len='2';
INSERT INTO products(id,name) VALUES (1,'iphone');
-->

<!-- request SQL -->

```sql
mysql> CALL AUTOCOMPLETE('hello', 'comment');
+------------+
| query      |
+------------+
| hello      |
| helio      |
| hell       |
| shell      |
| nushell    |
| powershell |
| well       |
| help       |
+------------+
```

<!-- request SQL with no fuzzy search -->

```sql
mysql> CALL AUTOCOMPLETE('hello', 'comment', 0 as fuzziness);
+-------+
| query |
+-------+
| hello |
+-------+
```

<!-- request JSON -->

```json
POST /autocomplete
{
	"table":"comment",
	"query":"hello"
}
```

<!-- response JSON -->
```json
[
  {
    "total": 8,
    "error": "",
    "warning": "",
    "columns": [
      {
        "query": {
          "type": "string"
        }
      }
    ],
    "data": [
      {
        "query": "hello"
      },
      {
        "query": "helio"
      },
      {
        "query": "hell"
      },
      {
        "query": "shell"
      },
      {
        "query": "nushell"
      },
      {
        "query": "powershell"
      },
      {
        "query": "well"
      },
      {
        "query": "help"
      }
    ]
  }
]
```

<!-- request SQL with preserve option -->

```sql
mysql> CALL AUTOCOMPLETE('hello wrld', 'comment', 1 as preserve);
+------------+
| query      |
+------------+
| hello wrld |
| hello world|
+------------+
```

<!-- request JSON with preserve option -->

```json
POST /autocomplete
{
	"table":"comment",
	"query":"hello wrld",
	"options": {
		"preserve": 1
	}
}
```

<!-- response JSON with preserve option -->
```json
[
  {
    "total": 2,
    "error": "",
    "warning": "",
    "columns": [
      {
        "query": {
          "type": "string"
        }
      }
    ],
    "data": [
      {
        "query": "hello wrld"
      },
      {
        "query": "hello world"
      }
    ]
  }
]
```

<!-- end -->

<!-- example force_bigrams option -->
##### Использование force_bigrams для лучшей обработки перестановок
Опция `force_bigrams` помогает с словами, в которых есть ошибки перестановки символов, такими как «ipohne» вместо «iphone». Используя биграммы вместо триграмм, алгоритм лучше справляется с перестановками символов.

<!-- request SQL -->
```sql
mysql> CALL AUTOCOMPLETE('ipohne', 'products', 1 as force_bigrams);
```

<!-- response SQL -->
```
+--------+
| query  |
+--------+
| iphone |
+--------+
```

<!-- request JSON -->
```json
POST /autocomplete
{
	"table":"products",
	"query":"ipohne",
	"options": {
		"force_bigrams": 1
	}
}
```

<!-- response JSON -->
```json
[
  {
    "total": 1,
    "error": "",
    "warning": "",
    "columns": [
      {
        "query": {
          "type": "string"
        }
      }
    ],
    "data": [
      {
        "query": "iphone"
      }
    ]
  }
]
```

<!-- end -->

#### Ссылки
* [Демонстрация](https://github.manticoresearch.com/manticoresoftware/manticoresearch) демонстрирующая функциональность автозаполнения:
  ![Пример автозаполнения](autocomplete_github_demo.png){.scale-0.7}
* Блог о нечетком поиске и автозаполнении - https://manticoresearch.com/blog/new-fuzzy-search-and-autocomplete/

## Альтернативные методы автозаполнения

Хотя `CALL AUTOCOMPLETE` является рекомендуемым методом для большинства случаев, Manticore также поддерживает другие управляемые и настраиваемые подходы для реализации функции автозаполнения:

##### Автозаполнение предложения
Чтобы автозаполнить предложение, можно использовать [инфиксный поиск](../Creating_a_table/NLP_and_tokenization/Wildcard_searching_settings.md#min_infix_len). Можно найти конец поля документа, указав его начало и:
* используя [оператор подстановки full-text](../Searching/Full_text_matching/Operators.md) `*` для совпадения с любыми символами
* при желании используя `^` для начала с начала поля
* при желании используя `""` для поиска фраз
* и используя [подсветку результатов](../Searching/Highlighting.md)

В нашем [блоге есть статья об этом](https://manticoresearch.com/blog/simple-autocomplete-with-manticore/) и [интерактивный курс](https://play.manticoresearch.com/simpleautocomplete/). Быстрый пример:
* Предположим, у вас есть документ: `Мой кот любит мою собаку. Кот (Felis catus) - это домашний вид небольшого плотоядного млекопитающего.`
* Тогда вы можете использовать `^`, `""` и `*`, так что, пока пользователь печатает, вы делаете запросы, такие как: `^"м*"`, `^"мой *"`, `^"мой к*"`, `^"мой ко*"` и так далее
* Это найдет документ, и если вы также сделаете [выделение](../Searching/Highlighting.md), вы получите что-то вроде: `<b>Мой кот</b> любит мою собаку. Кот ( ...`

##### Автозаполнение слова
В некоторых случаях все, что вам нужно, это автозаполнить одно слово или пару слов. В этом случае вы можете использовать `CALL KEYWORDS`.

### CALL KEYWORDS
`CALL KEYWORDS` доступен через SQL интерфейс и предлагает способ изучить, как ключевые слова токенизируются или получить токенизированные формы конкретных ключевых слов. Если таблица позволяет [инфиксы](../Creating_a_table/NLP_and_tokenization/Wildcard_searching_settings.md#min_infix_len), это позволяет вам быстро находить возможные окончания для заданных ключевых слов, что делает его подходящим для функции автозаполнения.

Это отличная альтернатива общему инфиксному поиску, так как она обеспечивает более высокую производительность, поскольку ей нужен только словарь таблицы, а не сами документы.

### Общий синтаксис
<!-- example keywords -->
```sql
CALL KEYWORDS(text, table [, options])
```
Оператор `CALL KEYWORDS` делит текст на ключевые слова. Он возвращает токенизированные и нормализованные формы ключевых слов, а также, если это необходимо, статистику ключевых слов. Кроме того, он предоставляет позицию каждого ключевого слова в запросе и все формы токенизированных ключевых слов, когда таблица позволяет [лемматизаторы](../Creating_a_table/NLP_and_tokenization/Morphology.md).

| Параметр | Описание |
| - | - |
| text | Текст для разбивки на ключевые слова |
| table | Имя таблицы, из которой брать настройки обработки текста |
| 0/1 как stats | Показать статистику ключевых слов, по умолчанию 0 |
| 0/1 как fold_wildcards | Сложить подстановочные знаки, по умолчанию 0 |
| 0/1 как fold_lemmas | Сложить морфологические леммы, по умолчанию 0 |
| 0/1 как fold_blended | Сложить смешанные слова, по умолчанию 0 |
| N как expansion_limit | Переопределить [expansion_limit](../Creating_a_table/NLP_and_tokenization/Wildcard_searching_settings.md#expansion_limit), определенный в конфигурации сервера, по умолчанию 0 (использовать значение из конфигурации) |
| docs/hits как sort_mode | Сортирует выходные результаты по 'docs' или 'hits'. По умолчанию сортировка не применяется. |
| jieba_mode | Режим сегментации Jieba для запроса. См. [jieba_mode](../Creating_a_table/NLP_and_tokenization/Morphology.md#jieba_mode) для получения дополнительных сведений |

Примеры показывают, как это работает, если предположить, что пользователь пытается получить автозаполнение для "мой кот ...". Таким образом, на стороне приложения все, что вам нужно сделать, это предложить пользователю окончания из столбца "нормализованный" для каждого нового слова. Часто имеет смысл сортировать по hits или docs, используя `'hits' как sort_mode` или `'docs' как sort_mode`.

<!-- intro -->
##### Примеры:

<!-- request Examples -->

```sql
MySQL [(none)]> CALL KEYWORDS('m*', 't', 1 as stats);
+------+-----------+------------+------+------+
| qpos | tokenized | normalized | docs | hits |
+------+-----------+------------+------+------+
| 1    | m*        | my         | 1    | 2    |
| 1    | m*        | mammal     | 1    | 1    |
+------+-----------+------------+------+------+

MySQL [(none)]> CALL KEYWORDS('my*', 't', 1 as stats);
+------+-----------+------------+------+------+
| qpos | tokenized | normalized | docs | hits |
+------+-----------+------------+------+------+
| 1    | my*       | my         | 1    | 2    |
+------+-----------+------------+------+------+

MySQL [(none)]> CALL KEYWORDS('c*', 't', 1 as stats, 'hits' as sort_mode);
+------+-----------+-------------+------+------+
| qpos | tokenized | normalized  | docs | hits |
+------+-----------+-------------+------+------+
| 1    | c*        | cat         | 1    | 2    |
| 1    | c*        | carnivorous | 1    | 1    |
| 1    | c*        | catus       | 1    | 1    |
+------+-----------+-------------+------+------+

MySQL [(none)]> CALL KEYWORDS('ca*', 't', 1 as stats, 'hits' as sort_mode);
+------+-----------+-------------+------+------+
| qpos | tokenized | normalized  | docs | hits |
+------+-----------+-------------+------+------+
| 1    | ca*       | cat         | 1    | 2    |
| 1    | ca*       | carnivorous | 1    | 1    |
| 1    | ca*       | catus       | 1    | 1    |
+------+-----------+-------------+------+------+

MySQL [(none)]> CALL KEYWORDS('cat*', 't', 1 as stats, 'hits' as sort_mode);
+------+-----------+------------+------+------+
| qpos | tokenized | normalized | docs | hits |
+------+-----------+------------+------+------+
| 1    | cat*      | cat        | 1    | 2    |
| 1    | cat*      | catus      | 1    | 1    |
+------+-----------+------------+------+------+
```
<!-- end -->

<!-- example bigram -->
Есть хороший трюк, как вы можете улучшить вышеуказанный алгоритм - используйте [bigram_index](../Creating_a_table/NLP_and_tokenization/Low-level_tokenization.md#bigram_index). Когда вы включаете его для таблицы, то получаете не просто одно слово, а каждую пару слов, стоящих друг за другом, индексируемую как отдельный токен.

Это позволяет предсказывать не только окончание текущего слова, но и следующее слово, что особенно полезно для автозаполнения.

<!-- intro -->
##### Примеры:

<!-- request Examples -->

```sql
MySQL [(none)]> CALL KEYWORDS('m*', 't', 1 as stats, 'hits' as sort_mode);
+------+-----------+------------+------+------+
| qpos | tokenized | normalized | docs | hits |
+------+-----------+------------+------+------+
| 1    | m*        | my         | 1    | 2    |
| 1    | m*        | mammal     | 1    | 1    |
| 1    | m*        | my cat     | 1    | 1    |
| 1    | m*        | my dog     | 1    | 1    |
+------+-----------+------------+------+------+

MySQL [(none)]> CALL KEYWORDS('my*', 't', 1 as stats, 'hits' as sort_mode);
+------+-----------+------------+------+------+
| qpos | tokenized | normalized | docs | hits |
+------+-----------+------------+------+------+
| 1    | my*       | my         | 1    | 2    |
| 1    | my*       | my cat     | 1    | 1    |
| 1    | my*       | my dog     | 1    | 1    |
+------+-----------+------------+------+------+

MySQL [(none)]> CALL KEYWORDS('c*', 't', 1 as stats, 'hits' as sort_mode);
+------+-----------+--------------------+------+------+
| qpos | tokenized | normalized         | docs | hits |
+------+-----------+--------------------+------+------+
| 1    | c*        | cat                | 1    | 2    |
| 1    | c*        | carnivorous        | 1    | 1    |
| 1    | c*        | carnivorous mammal | 1    | 1    |
| 1    | c*        | cat felis          | 1    | 1    |
| 1    | c*        | cat loves          | 1    | 1    |
| 1    | c*        | catus              | 1    | 1    |
| 1    | c*        | catus is           | 1    | 1    |
+------+-----------+--------------------+------+------+

MySQL [(none)]> CALL KEYWORDS('ca*', 't', 1 as stats, 'hits' as sort_mode);
+------+-----------+--------------------+------+------+
| qpos | tokenized | normalized         | docs | hits |
+------+-----------+--------------------+------+------+
| 1    | ca*       | cat                | 1    | 2    |
| 1    | ca*       | carnivorous        | 1    | 1    |
| 1    | ca*       | carnivorous mammal | 1    | 1    |
| 1    | ca*       | cat felis          | 1    | 1    |
| 1    | ca*       | cat loves          | 1    | 1    |
| 1    | ca*       | catus              | 1    | 1    |
| 1    | ca*       | catus is           | 1    | 1    |
+------+-----------+--------------------+------+------+

MySQL [(none)]> CALL KEYWORDS('cat*', 't', 1 as stats, 'hits' as sort_mode);
+------+-----------+------------+------+------+
| qpos | tokenized | normalized | docs | hits |
+------+-----------+------------+------+------+
| 1    | cat*      | cat        | 1    | 2    |
| 1    | cat*      | cat felis  | 1    | 1    |
| 1    | cat*      | cat loves  | 1    | 1    |
| 1    | cat*      | catus      | 1    | 1    |
| 1    | cat*      | catus is   | 1    | 1    |
+------+-----------+------------+------+------+
```
<!-- end -->

`CALL KEYWORDS` поддерживает распределенные таблицы, так что независимо от того, насколько велик ваш набор данных, вы можете извлечь выгоду от его использования.
<!-- proofread -->

