# Параметры поиска

SQL-предложение [SELECT](../Searching/Full_text_matching/Basic_usage.md#SQL) и HTTP-эндпоинт [/search](../Searching/Full_text_matching/Basic_usage.md#HTTP-JSON) поддерживают ряд опций, которые можно использовать для тонкой настройки поведения поиска.

## OPTION

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

<!-- example options -->

**SQL**:

```sql
SELECT ... [OPTION <optionname>=<value> [ , ... ]] [/*+ [NO_][ColumnarScan|DocidIndex|SecondaryIndex(<attribute>[,...])]] /*]
```

**HTTP**:
```json
POST /search
{
    "table" : "table_name",
    "options":
    {
        "optionname": "value",
        "optionname2": <value2>
    }
}
```


<!-- intro -->
SQL:
<!-- request SQL -->

<!--
data for the following example:

DROP TABLE IF EXISTS test;
CREATE TABLE test(title text, body text);
INSERT INTO test(id,title,body) VALUES (1,'hello','world');
-->
```sql
SELECT * FROM test WHERE MATCH('@title hello @body world')
OPTION ranker=bm25, max_matches=3000,
field_weights=(title=10, body=3), agent_query_timeout=10000
```

<!-- response SQL -->
```sql
+------+-------+-------+
| id   | title | body  |
+------+-------+-------+
|    1 | hello | world |
+------+-------+-------+
1 row in set (0.00 sec)
```

<!-- intro -->
JSON:
<!-- request JSON -->

```json
POST /search
{
    "table" : "test",
    "query": {
      "bool": {
        "must": [
          {
            "match": {
              "title": "hello"
            }
          },
          {
            "match": {
              "body": "world"
            }
          }
        ]
      }
    },
    "options":
    {
        "ranker": "bm25",
        "max_matches": 3000,
        "field_weights": {
            "title": 10,
            "body": 3
        },
        "agent_query_timeout": 10000
    }
}
```

<!-- response JSON -->

```json
{
  "took": 0,
  "timed_out": false,
  "hits": {
    "total": 1,
    "total_relation": "eq",
    "hits": [
      {
        "_id": 1,
        "_score": 10500,
        "_source": {
          "title": "hello",
          "body": "world"
        }
      }
    ]
  }
}
```

<!-- end -->

Поддерживаемые опции:

### accurate_aggregation
Целое число. Включает или отключает гарантированную точность агрегации при выполнении групповых запросов в нескольких потоках. По умолчанию 0.

При выполнении группового запроса он может выполняться параллельно на обычной таблице с несколькими псевдошардами (если включен `pseudo_sharding`). Аналогичный подход работает на RT-таблицах. Каждый шард/чанк выполняет запрос, но количество групп ограничено `max_matches`. Если результирующие наборы из разных шардов/чанков содержат разные группы, подсчет групп и агрегаты могут быть неточными. Обратите внимание, что Manticore пытается увеличить `max_matches` до [`max_matches_increase_threshold`](../Searching/Options.md#max_matches_increase_threshold) на основе количества уникальных значений группирующего атрибута (полученных из вторичных индексов). Если это удается, потери точности не будет.

Однако, если количество уникальных значений группирующего атрибута велико, дальнейшее увеличение `max_matches` может быть не лучшей стратегией, так как это может привести к потере производительности и увеличению использования памяти. Установка `accurate_aggregation` в 1 заставляет групповые поиски выполняться в одном потоке, что решает проблему точности. Обратите внимание, что выполнение в одном потоке применяется только тогда, когда `max_matches` не может быть установлен достаточно высоким; в противном случае поиски с `accurate_aggregation=1` все равно будут выполняться в нескольких потоках.

В целом, установка `accurate_aggregation` в 1 гарантирует точность подсчета групп и агрегатов в RT-таблицах и обычных таблицах с `pseudo_sharding=1`. Недостаток в том, что поиски будут выполняться медленнее, так как они будут вынуждены работать в одном потоке.

Однако, если у нас есть RT-таблица и обычная таблица, содержащие одни и те же данные, и мы выполняем запрос с `accurate_aggregation=1`, мы все равно можем получить разные результаты. Это происходит потому, что демон может выбрать разные настройки `max_matches` для RT-таблицы и обычной таблицы из-за настройки [`max_matches_increase_threshold`](../Searching/Options.md#max_matches_increase_threshold).

### agent_query_timeout
Целое число. Максимальное время в миллисекундах ожидания завершения удаленных запросов, см. [этот раздел](../Creating_a_table/Creating_a_distributed_table/Remote_tables.md#agent_query_timeout).

### boolean_simplify
`0` или `1` (по умолчанию `1`). `boolean_simplify=1` включает [упрощение запроса](../Searching/Full_text_matching/Boolean_optimization.md) для ускорения его выполнения.

Эта опция также может быть установлена глобально в [конфигурации searchd](../Server_settings/Searchd.md#boolean_simplify) для изменения поведения по умолчанию для всех запросов. Опция на уровне запроса переопределит глобальную настройку.

### comment
Строка, пользовательский комментарий, который копируется в файл журнала запросов.

### cutoff
Целое число. Определяет максимальное количество совпадений для обработки. Если не установлено, Manticore автоматически выберет подходящее значение.

<!-- example cutoff_aggregation -->

* `N = 0`: Отключает ограничение на количество совпадений.
* `N > 0`: Указывает Manticore остановить обработку результатов, как только будет найдено `N` соответствующих документов.
* Не установлено: Manticore определяет порог автоматически.

Когда Manticore не может определить точное количество соответствующих документов, поле `total_relation` в [метаинформации](../Node_info_and_management/SHOW_META.md#SHOW-META) запроса будет показывать `gte`, что означает **Больше или Равно**. Это указывает, что фактическое количество совпадений составляет по меньшей мере указанное `total_found` (в SQL) или `hits.total` (в JSON). Когда количество точное, `total_relation` будет отображать `eq`.

Примечание: Использование `cutoff` в агрегационных запросах не рекомендуется, так как это может привести к неточным или неполным результатам.

<!-- request Example -->

Использование `cutoff` в агрегационных запросах может привести к некорректным или вводящим в заблуждение результатам, как показано в следующем примере:
```
drop table if exists t
--------------

Query OK, 0 rows affected (0.02 sec)

--------------
create table t(a int)
--------------

Query OK, 0 rows affected (0.04 sec)

--------------
insert into t(a) values(1),(2),(3),(1),(2),(3)
--------------

Query OK, 6 rows affected (0.00 sec)

--------------
select avg(a) from t option cutoff=1 facet a
--------------

+----------+
| avg(a)   |
+----------+
| 1.000000 |
+----------+
1 row in set (0.00 sec)
--- 1 out of 1 results in 0ms ---

+------+----------+
| a    | count(*) |
+------+----------+
|    1 |        1 |
+------+----------+
1 row in set (0.00 sec)
--- 1 out of 1 results in 0ms ---
```

Сравните с тем же запросом без `cutoff`:
```
--------------
select avg(a) from t facet a
--------------

+----------+
| avg(a)   |
+----------+
| 2.000000 |
+----------+
1 row in set (0.00 sec)
--- 1 out of 1 results in 0ms ---

+------+----------+
| a    | count(*) |
+------+----------+
|    1 |        2 |
|    2 |        2 |
|    3 |        2 |
+------+----------+
3 rows in set (0.00 sec)
--- 3 out of 3 results in 0ms ---
```

<!-- end -->

### distinct_precision_threshold
Целое число. По умолчанию `3500`. Эта опция устанавливает порог, ниже которого количества, возвращаемые `count distinct`, гарантированно точны в пределах обычной таблицы.

Допустимые значения в диапазоне от `500` до `15500`. Значения вне этого диапазона будут ограничены.

Когда эта опция установлена в 0, включается алгоритм, гарантирующий точные подсчеты. Этот алгоритм собирает пары `{группа, значение}`, сортирует их и периодически удаляет дубликаты. Результат — точные подсчеты в пределах обычной таблицы. Однако этот подход не подходит для наборов данных с высокой кардинальностью из-за высокого потребления памяти и медленного выполнения запроса.

Когда `distinct_precision_threshold` установлен в значение больше `0`, Manticore использует другой алгоритм. Он загружает подсчеты в хеш-таблицу и возвращает размер таблицы. Если хеш-таблица становится слишком большой, ее содержимое перемещается в структуру данных `HyperLogLog`. На этом этапе подсчеты становятся приблизительными, поскольку HyperLogLog — это вероятностный алгоритм. Этот подход поддерживает фиксированное максимальное использование памяти на группу, но есть компромисс в точности подсчетов.

Точность `HyperLogLog` и порог преобразования из хеш-таблицы в HyperLogLog определяются настройкой `distinct_precision_threshold`. Важно использовать эту опцию с осторожностью, поскольку удвоение ее значения также удвоит максимальный объем памяти, необходимый для вычисления подсчетов. Максимальное использование памяти можно приблизительно оценить по формуле: `64 * max_matches * distinct_precision_threshold`, хотя на практике вычисления подсчетов часто используют меньше памяти, чем в худшем случае.

### expand_keywords
`0` или `1` (по умолчанию `0`). Расширяет ключевые слова точными формами и/или звездочками, когда это возможно. Подробнее см. [expand_keywords](../Creating_a_table/NLP_and_tokenization/Wildcard_searching_settings.md#expand_keywords).

### expand_blended
`0`, `off`, `1` или любая комбинация опций `blend_mode` (по умолчанию `0`). Расширяет смешанные ключевые слова (токены, содержащие символы, настроенные через [blend_chars](../Creating_a_table/NLP_and_tokenization/Low-level_tokenization.md#blend_chars)) на их составные варианты во время разбора запроса. При включении ключевые слова, такие как "well-being" (если `-` настроен в `blend_chars`), расширяются в варианты, такие как "well-being", "wellbeing", "well" и "being", которые затем группируются в поддеревья ИЛИ в дереве запроса.

Поддерживаемые значения:
* `0` или `off` - Расширение смешанных слов отключено (по умолчанию). Смешанные ключевые слова обрабатываются обычным образом без расширения.
* `1` - Расширение смешанных слов включено и использует настройку [blend_mode](../Creating_a_table/NLP_and_tokenization/Low-level_tokenization.md#blend_mode) таблицы для определения, какие варианты генерировать.
* Любая опция(и) режима смешивания - Расширение смешанных слов включено с указанным режимом(ами) смешивания, переопределяя настройку `blend_mode` таблицы.

Подробнее об опциях см. [blend_mode](../Creating_a_table/NLP_and_tokenization/Low-level_tokenization.md#blend_mode).

### fusion_method
Строка. Включает слияние результатов [гибридного поиска](../Searching/Hybrid_search.md). В настоящее время единственное поддерживаемое значение — `'rrf'` (Reciprocal Rank Fusion). При установке `MATCH(...)` и `KNN(...)` выполняются как независимые подзапросы, результаты которых объединяются по рангу.

```sql
SELECT id, hybrid_score() FROM t
WHERE match('machine learning') AND knn(vec, 5, (0.1, 0.1, 0.1, 0.1))
OPTION fusion_method='rrf';
```

### fusion_weights
Именованный список чисел с плавающей запятой. Веса для каждого подзапроса при оценке RRF в [гибридном поиске](../Searching/Hybrid_search.md). Требует `fusion_method='rrf'`. Подзапросам должны быть явно присвоены псевдонимы с помощью `AS` в SQL или `"name"` в JSON. Для неуказанных псевдонимов по умолчанию используется вес 1.0.

```sql
SELECT id, hybrid_score() FROM t
WHERE match('machine learning') AS text
  AND knn(vec, 5, (0.1, 0.1, 0.1, 0.1)) AS dense
OPTION fusion_method='rrf', fusion_weights=(text=0.7, dense=0.3);
```

### field_weights
Именованный список целых чисел (пользовательские веса по полям для ранжирования).

Пример:
```sql
SELECT ... OPTION field_weights=(title=10, body=3)
```

### global_idf
Использовать глобальную статистику (частоты) из файла [global_idf](../Creating_a_table/NLP_and_tokenization/Low-level_tokenization.md#global_idf) для вычислений IDF.

### idf
Заключенный в кавычки список флагов вычисления IDF, разделенных запятыми. Известные флаги:

* `normalized`: вариант BM25, idf = log((N-n+1)/n), согласно Robertson et al
* `plain`: простой вариант, idf = log(N/n), согласно Sparck-Jones
* `tfidf_normalized`: дополнительно делить IDF на количество слов в запросе, чтобы `TF*IDF` попадал в диапазон [0, 1]
* `tfidf_unnormalized`: не делить дополнительно IDF на количество слов в запросе, где N - размер коллекции, а n - количество совпадающих документов

Исторически используемый по умолчанию IDF (обратная частота документа) в Manticore эквивалентен `OPTION idf='normalized,tfidf_normalized'`, и эти нормализации могут вызывать несколько нежелательных эффектов.

Во-первых, `idf=normalized` приводит к штрафованию ключевых слов. Например, если вы ищете `the | something` и `the` встречается более чем в 50% документов, то документы с обоими ключевыми словами `the` и `something` получат меньший вес, чем документы только с одним ключевым словом `something`. Использование `OPTION idf=plain` позволяет избежать этого. Простой IDF варьируется в диапазоне `[0, log(N)]`, и ключевые слова никогда не штрафуются; в то время как нормализованный IDF варьируется в диапазоне `[-log(N), log(N)]`, и слишком частые ключевые слова штрафуются.

Во-вторых, `idf=tfidf_normalized` приводит к смещению IDF между запросами. Исторически IDF также делился на количество ключевых слов в запросе, гарантируя, что вся `sum(tf*idf)` по всем ключевым словам остается в пределах диапазона [0,1]. Однако это означало, что запросы типа `word1` и `word1 | nonmatchingword2` присваивали разные веса одному и тому же набору результатов, поскольку IDF как для `word1`, так и для `nonmatchingword2` делились на 2. Использование `OPTION idf='tfidf_unnormalized'` решает эту проблему. Имейте в виду, что факторы ранжирования BM25, BM25A, BM25F() будут соответствующим образом скорректированы при отключении этой нормализации.

Флаги IDF можно комбинировать; `plain` и `normalized` являются взаимоисключающими; `tfidf_unnormalized` и `tfidf_normalized` также являются взаимоисключающими; и неуказанные флаги в таких взаимоисключающих группах по умолчанию сохраняют свои исходные настройки. Это означает, что `OPTION idf=plain` эквивалентно полному указанию `OPTION idf='plain,tfidf_normalized'`.

### jieba_mode
Определяет режим сегментации Jieba для запроса.

При использовании китайской сегментации Jieba иногда может быть полезно использовать разные режимы сегментации для токенизации документов и запроса. Полный список режимов см. в [jieba_mode](../Creating_a_table/NLP_and_tokenization/Morphology.md#jieba_mode).

### index_weights
Именованный список целых чисел. Пользовательские веса по таблицам для ранжирования.

### local_df
`0` или `1`, автоматически суммировать DF по всем локальным частям распределенной таблицы, обеспечивая согласованные (и точные) IDF для локально шардированной таблицы. По умолчанию включено для дисковых чанков RT-таблицы. Термины запроса с подстановочными знаками игнорируются.

### low_priority
`0` или `1` (по умолчанию `0`). Установка `low_priority=1` выполняет запрос с более низким приоритетом, перепланируя его задачи в 10 раз реже, чем другие запросы с обычным приоритетом.

### max_matches
Целое число. Значение максимального количества совпадений на запрос.

Максимальное количество совпадений, которое сервер хранит в оперативной памяти для каждой таблицы и может вернуть клиенту. По умолчанию равно 1000.

Введенная для контроля и ограничения использования оперативной памяти, настройка `max_matches` определяет, сколько совпадений будет храниться в оперативной памяти при поиске по каждой таблице. Каждое найденное совпадение все равно обрабатывается, но только лучшие N из них будут сохранены в памяти и в конечном итоге возвращены клиенту. Например, предположим, что таблица содержит 2 000 000 совпадений для запроса. Редко возникает необходимость получить их все. Вместо этого вам нужно просканировать их все, но выбрать только "лучшие" 500, например, на основе некоторых критериев (например, отсортированных по релевантности, цене или другим факторам) и отобразить эти 500 совпадений конечному пользователю страницами по 20-100 совпадений. Отслеживание только лучших 500 совпадений гораздо эффективнее по использованию оперативной памяти и процессора, чем хранение всех 2 000 000 совпадений, их сортировка, а затем отбрасывание всего, кроме первых 20, необходимых для страницы результатов поиска. `max_matches` контролирует N в этом количестве "лучших N".

Этот параметр значительно влияет на использование оперативной памяти и процессора для каждого запроса. Значения от 1 000 до 10 000 обычно приемлемы, но более высокие лимиты следует использовать с осторожностью. Бездумное увеличение max_matches до 1 000 000 означает, что `searchd` должен будет выделять и инициализировать буфер совпадений на 1 миллион записей для каждого запроса. Это неизбежно увеличит использование оперативной памяти на запрос и, в некоторых случаях, может заметно повлиять на производительность.

Обратитесь к [max_matches_increase_threshold](../Searching/Options.md#max_matches_increase_threshold) для получения дополнительной информации о том, как это может повлиять на поведение опции `max_matches`.

### max_matches_increase_threshold

Целое число. Устанавливает порог, до которого можно увеличить `max_matches`. По умолчанию 16384.

Manticore может увеличить `max_matches` для повышения точности группировки и/или агрегации, когда включен `pseudo_sharding`, и если он обнаруживает, что количество уникальных значений атрибута группировки меньше этого порога. Потеря точности может произойти, когда псевдошардирование выполняет запрос в нескольких потоках или когда RT-таблица проводит параллельный поиск в дисковых чанках.

Если количество уникальных значений атрибута группировки меньше порога, `max_matches` будет установлено в это число. В противном случае будет использовано значение `max_matches` по умолчанию.

Если `max_matches` было явно установлено в параметрах запроса, этот порог не действует.

Имейте в виду, что если этот порог установлен слишком высоко, это приведет к увеличению потребления памяти и общему снижению производительности.

Вы также можете принудительно включить режим гарантированной точности группировки/агрегации с помощью опции [accurate_aggregation](../Searching/Options.md#accurate_aggregation).

### max_query_time
Устанавливает максимальное время выполнения поискового запроса в миллисекундах. Должно быть неотрицательным целым числом. Значение по умолчанию — 0, что означает «не ограничивать». Локальные поисковые запросы будут остановлены, как только истечет указанное время. Обратите внимание, что если вы выполняете поиск, который запрашивает несколько локальных таблиц, этот лимит применяется к каждой таблице отдельно. Имейте в виду, что это может немного увеличить время отклика запроса из-за накладных расходов, вызванных постоянным отслеживанием, не пора ли остановить запрос.

### morphology
`none` позволяет заменять все термины запроса их точными формами, если таблица была построена с включенной опцией [index_exact_words](../Creating_a_table/NLP_and_tokenization/Morphology.md#index_exact_words). Это полезно для предотвращения стемминга или лемматизации терминов запроса.

### not_terms_only_allowed

<!--
data for the following example:

DROP TABLE IF EXISTS t;
CREATE TABLE t(f1 text, f2 int);
INSERT INTO t(f1, f2) VALUES
('b', 2),
('c', 3),
('b', 2);
-->

<!-- example not_terms_only_allowed -->
`0` или `1` разрешает автономное [отрицание](../Searching/Full_text_matching/Operators.md#Negation-operator) для запроса. По умолчанию 0. См. также соответствующую [глобальную настройку](../Server_settings/Searchd.md#not_terms_only_allowed).

<!-- request SQL -->
```sql
MySQL [(none)]> select * from t where match('-donald');
ERROR 1064 (42000): index t: query error: query is non-computable (single NOT operator)
MySQL [(none)]> select * from t where match('-donald') option not_terms_only_allowed=1;
+---------------------+-----------+
| id                  | field     |
+---------------------+-----------+
| 1658178727135150081 | smth else |
+---------------------+-----------+
```

<!-- request JSON -->
```JSON
POST /sql -d "select * from t where match('-d')"
{
  "error": "table t: query error: query is non-computable (single NOT operator)"
}
POST /sql -d "select * from t where match('-d')  option not_terms_only_allowed=1"
{
  "took": 0,
  "timed_out": false,
  "hits": {
    "total": 3,
    "total_relation": "eq",
    "hits": [
      {
        "_id": 724024784404348900,
        "_score": 2500,
        "_source": {
          "f1": "b",
          "f2": 2
        }
      },
      {
        "_id": 5912226830793834497,
        "_score": 2500,
        "_source": {
          "f1": "c",
          "f2": 3
        }
      },
      {
        "_id": 724024784404348900,
        "_score": 2500,
        "_source": {
          "f1": "b",
          "f2": 2
        }
      }
    ]
  }
}
```

<!-- end -->

### rank_constant
Целое число. По умолчанию 60. Константа сглаживания для ранжирования RRF в [гибридном поиске](../Searching/Hybrid_search.md). Оценка каждого документа из подзапроса рассчитывается как `weight / (rank_constant + rank)`, где `rank` — его позиция (начиная с 1) в результатах этого подзапроса. Меньшее значение (например, 10) делает первые позиции гораздо более значимыми, чем последующие; большее значение (например, 100) сглаживает разницу между позициями. Требует `fusion_method='rrf'`.

```sql
SELECT id, hybrid_score() FROM t
WHERE match('machine learning') AND knn(vec, 5, (0.1, 0.1, 0.1, 0.1))
OPTION fusion_method='rrf', rank_constant=10;
```

### boolean_mode

```sql
OPTION boolean_mode='or'
```

Определяет, как выражения `MATCH()` с несколькими ключевыми словами **без явных логических операторов** интерпретируются в полнотекстовых запросах SphinxQL.

Выберите одно из следующих значений:
* `and` - должны совпасть все ключевые слова
* `or` - может совпасть любое ключевое слово

`OPTION boolean_mode=...` действует только для текущего запроса. Также можно сохранить режим boolean по умолчанию в метаданных таблицы с помощью `CREATE TABLE ... boolean_mode='...'` или используя [profile](../Creating_a_table/Local_tables/Plain_and_real-time_table_settings.md#profile) таблицы. Если заданы оба, приоритет имеет опция запроса. Если не задано ни одно, SQL по умолчанию использует `and`.

Он влияет только на **неявный** объединитель между соседними ключевыми словами или подвыражениями, у которых еще нет явного полнотекстового оператора. Явные операторы, такие как `|`, `!`/`-`, фразы, quorum, `NEAR` и `<<`, сохраняют свою семантику.

В HTTP JSON есть собственный эквивалент для запросов `match` через свойство `"operator"`, которое по умолчанию равно `or`, если не задано явно.

### ranker
Выберите из следующих вариантов:
* `proximity_bm25`
* `bm25`
* `none`
* `wordcount`
* `proximity`
* `matchany`
* `fieldmask`
* `sph04`
* `expr`
* `export`

Для получения более подробной информации о каждом ранкере обратитесь к [Ранжирование результатов поиска](../Searching/Sorting_and_ranking.md#Available-built-in-rankers).

`OPTION ranker=...` задает ранжировщик только для текущего запроса. Также можно сохранить ранжировщик по умолчанию в метаданных таблицы с помощью `CREATE TABLE ... ranker='...'` или используя [profile](../Creating_a_table/Local_tables/Plain_and_real-time_table_settings.md#profile) таблицы. Если заданы оба, приоритет имеет опция запроса. Если запрос обращается к нескольким таблицам и не задает `OPTION ranker=...`, каждая таблица использует свой сохраненный ранжировщик по умолчанию, включая локальные и удаленные распределенные таблицы. Итоговое объединение использует сырые возвращенные веса без нормализации между разными ранжировщиками, поэтому глобальный порядок надежно сопоставим только тогда, когда участвующие таблицы используют одинаковую семантику ранжировщика.

### rand_seed
Позволяет указать конкретное целочисленное значение сида для запроса `ORDER BY RAND()`, например: `... OPTION rand_seed=1234`. По умолчанию для каждого запроса автоматически генерируется новое и разное значение сида.

### retry_count
Целое число. Количество повторных попыток для распределенного поиска.

### retry_delay
Целое число. Задержка между повторными попытками для распределенного поиска, в миллисекундах.

### scroll

Строка. Токен прокрутки для постраничного вывода результатов с использованием [Подхода к пагинации Scroll](../Searching/Pagination.md#Scroll-Search-Option).

### sort_method
* `pq` - очередь с приоритетом, установлена по умолчанию
* `kbuffer` - обеспечивает более быструю сортировку для уже предварительно отсортированных данных, например, данных таблицы, отсортированных по id
Результирующий набор одинаков в обоих случаях; выбор того или иного варианта может просто улучшить (или ухудшить) производительность.

### window_size
Целое число. По умолчанию 0 (авто). Управляет тем, сколько результатов каждый подзапрос (текстовый и каждый KNN) извлекает перед слиянием RRF в [гибридном поиске](../Searching/Hybrid_search.md). Большее окно подаёт больше кандидатов на слияние, улучшая полноту охвата за счёт производительности. Требует `fusion_method='rrf'`.

При установке в 0 (авто) окно вычисляется как **максимум** из:
- наибольшего запрошенного количества документов KNN среди всех KNN подзапросов (что составляет `k * oversampling`, когда повторное ранжирование включено, или просто `k` в противном случае), и
- значения `LIMIT` запроса.

Например, при `LIMIT 20` и `knn(vec, 10, ...)` (oversampling по умолчанию 3.0, повторное ранжирование включено), авто окно = max(10*3, 20) = 30. Как текстовый подзапрос, так и KNN подзапрос будут извлекать до 30 результатов каждый перед слиянием.

При явной установке это значение переопределяет автоматический расчёт и используется как лимит для всех подзапросов.

```sql
SELECT id, hybrid_score() FROM t
WHERE match('machine learning') AND knn(vec, 5, (0.1, 0.1, 0.1, 0.1))
OPTION fusion_method='rrf', window_size=50;
```

### threads
Ограничивает максимальное количество потоков, используемых для обработки текущего запроса. По умолчанию — без ограничений (запрос может занять все [потоки](../Server_settings/Searchd.md#threads), определенные глобально).
Для пакета запросов опция должна быть прикреплена к самому первому запросу в пакете, и затем она применяется при создании рабочей очереди и действует на весь пакет. Эта опция имеет тот же смысл, что и опция [max_threads_per_query](../Server_settings/Searchd.md#max_threads_per_query), но применяется только к текущему запросу или пакету запросов.

### token_filter
Заключенная в кавычки строка, разделенная двоеточиями: `имя библиотеки:имя плагина:необязательная строка настроек`. Фильтр токенов времени запроса создается для каждого поиска, когда полнотекстовый поиск вызывается каждой задействованной таблицей, позволяя реализовать пользовательский токенизатор, который генерирует токены в соответствии с пользовательскими правилами.
```sql
SELECT * FROM index WHERE MATCH ('yes@no') OPTION token_filter='mylib.so:blend:@'
```
### expansion_limit
Ограничивает максимальное количество расширенных ключевых слов для одного подстановочного знака, значение по умолчанию 0 означает отсутствие ограничений. Для получения дополнительных сведений обратитесь к [expansion_limit](../Server_settings/Searchd.md#expansion_limit).

## Подсказки оптимизатора запросов

<!-- example options_force -->

В редких случаях встроенный анализатор запросов Manticore может ошибаться в понимании запроса и определении того, следует ли использовать индекс docid, вторичные индексы или колоночное сканирование. Чтобы переопределить решения оптимизатора запросов, вы можете использовать следующие подсказки в своем запросе:

* `/*+ DocidIndex(id) */`  для принудительного использования индекса docid, `/*+ NO_DocidIndex(id) */` чтобы указать оптимизатору игнорировать его
* `/*+ SecondaryIndex(<attr_name1>[, <attr_nameN>]) */` для принудительного использования вторичного индекса (если доступен), `/*+ NO_SecondaryIndex(id) */`  чтобы указать оптимизатору игнорировать его
* `/*+ ColumnarScan(<attr_name1>[, <attr_nameN>]) */`  для принудительного использования колоночного сканирования (если атрибут колоночный), `/*+ NO_ColumnarScan(id) */` чтобы указать оптимизатору игнорировать его

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

Для получения дополнительной информации о том, как работает оптимизатор запросов, обратитесь к странице [Стоимостной оптимизатор](../Searching/Cost_based_optimizer.md).

<!-- request SQL -->

```sql
SELECT * FROM students where age > 21 /*+ SecondaryIndex(age) */
```

<!-- end -->

<!--
data for the following example:

DROP TABLE IF EXISTS students;
CREATE TABLE students(name text, age int);
INSERT INTO students(name, age) VALUES
('Alice', 20),
('Bob', 22),
('Carol', 25);
-->

<!-- example comments -->
При использовании клиента MySQL/MariaDB убедитесь, что включен флаг `--comments`, чтобы активировать подсказки в ваших запросах.

<!-- request mysql -->
```bash
mysql -P9306 -h0 --comments
```

<!-- request JSON -->

```JSON
POST /sql -d "SELECT * FROM students where age > 21 /*+ SecondaryIndex(age) */"
```

<!-- end -->

<!-- proofread -->

