Поиск с подстановочными знаками — это распространённый тип текстового поиска. В Manticore он выполняется на уровне словаря. По умолчанию как обычные, так и RT-таблицы используют тип словаря, называемый dict. В этом режиме слова хранятся в исходном виде, поэтому включение подстановочных знаков не влияет на размер таблицы. При выполнении поиска с подстановочными знаками словарь просматривается для нахождения всех возможных расширений слова с подстановочными знаками. Такое расширение может быть проблематичным с точки зрения вычислений во время запроса, если расширенное слово даёт много вариантов или варианты с огромными списками попаданий, особенно в случае инфиксов, когда подстановочный знак добавляется в начало и конец слова. Чтобы избежать таких проблем, можно использовать expansion_limit.
min_prefix_len = length
Этот параметр определяет минимальную длину префикса слова для индексации и поиска. По умолчанию он установлен в 0, что означает, что префиксы не разрешены.
Префиксы позволяют выполнять поиск с подстановочными знаками вида wordstart*.
Например, если слово "example" индексируется с min_prefix_len=3, его можно найти, выполнив поиск по "exa", "exam", "examp", "exampl", а также по полному слову.
Обратите внимание, что при использовании dict=crc min_prefix_len повлияет на размер полнотекстового индекса, так как каждое расширение слова будет храниться дополнительно.
Manticore может различать точные совпадения слов и совпадения по префиксу и ранжировать первые выше, если выполнены следующие условия:
- dict=keywords (включено по умолчанию)
- index_exact_words=1 (выключено по умолчанию),
- expand_keywords=1 (также выключено по умолчанию)
Обратите внимание, что при использовании режима dict=crc или при отключении любого из вышеуказанных параметров невозможно различать префиксы и полные слова, и точные совпадения слов не могут быть ранжированы выше.
Когда минимальная длина инфикса установлена в положительное число, минимальная длина префикса всегда считается равной 1.
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) min_prefix_len = '3'POST /cli -d "
CREATE TABLE products(title text, price float) min_prefix_len = '3'"$index = new \Manticoresearch\Index($client);
$index->setName('products');
$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'min_prefix_len' => '3'
]);utilsApi.sql('CREATE TABLE products(title text, price float) min_prefix_len = \'3\'')await utilsApi.sql('CREATE TABLE products(title text, price float) min_prefix_len = \'3\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) min_prefix_len = \'3\'');utilsApi.sql("CREATE TABLE products(title text, price float) min_prefix_len = '3'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) min_prefix_len = '3'", true);utils_api.sql("CREATE TABLE products(title text, price float) min_prefix_len = '3'", Some(true)).await;table products {
min_prefix_len = 3
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}min_infix_len = length
Параметр min_infix_len определяет минимальную длину префикса инфикса для индексации и поиска. Он является необязательным, и его значение по умолчанию равно 0, что означает, что инфиксы не разрешены. Минимально допустимое ненулевое значение — 2.
При включении инфиксы позволяют выполнять поиск с подстановочными знаками с шаблонами терминов, такими как start*, *end, *middle* и так далее. Это также позволяет отключить слишком короткие подстановочные знаки, если их поиск слишком затратен.
Если выполнены следующие условия, Manticore может различать точные совпадения слов и совпадения по инфиксу и ранжировать первые выше:
- dict=keywords (включено по умолчанию)
- index_exact_words=1 (выключено по умолчанию),
- expand_keywords=1 (также выключено по умолчанию)
Обратите внимание, что при использовании режима dict=crc или при отключении любого из вышеуказанных параметров невозможно различать инфиксы и полные слова, и, следовательно, точные совпадения слов не могут быть ранжированы выше.
Время выполнения запроса поиска с подстановочными знаками в инфиксах может сильно варьироваться в зависимости от того, на сколько ключевых слов будет расширяться подстрока. Короткие и частые слоги, такие как *in* или *ti*, могут расширяться до слишком большого количества ключевых слов, все из которых нужно будет сопоставить и обработать. Поэтому для общего включения поиска подстрок обычно устанавливают min_infix_len в 2. Чтобы ограничить влияние поиска с подстановочными знаками с слишком короткими подстановочными знаками, можно установить его выше.
Инфиксы должны быть длиной не менее 2 символов, и подстановочные знаки вида *a* не разрешены по причинам производительности.
Когда min_infix_len установлен в положительное число, минимальная длина префикса считается равной 1. Для dict нельзя одновременно включать инфиксы и префиксы. Для dict и других полей, чтобы иметь префиксы, объявленные с помощью prefix_fields, запрещено объявлять одно и то же поле в обоих списках.
Если dict=keywords, кроме подстановочного знака *, можно использовать ещё два символа подстановки:
?может соответствовать любому (одному) символу:t?stсовпадёт сtest, но не сteast%может соответствовать нулю или одному символу:tes%совпадёт сtesилиtest, но не сtesting
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) min_infix_len = '3'POST /cli -d "
CREATE TABLE products(title text, price float) min_infix_len = '3'"$index = new \Manticoresearch\Index($client);
$index->setName('products');
$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'min_infix_len' => '3'
]);utilsApi.sql('CREATE TABLE products(title text, price float) min_infix_len = \'3\'')await utilsApi.sql('CREATE TABLE products(title text, price float) min_infix_len = \'3\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) min_infix_len = \'3\'');utilsApi.sql("CREATE TABLE products(title text, price float) min_infix_len = '3'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) min_infix_len = '3'", true);utils_api.sql("CREATE TABLE products(title text, price float) min_infix_len = '3'", Some(true)).await;table products {
min_infix_len = 3
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}prefix_fields = field1[, field2, ...]
Настройка prefix_fields используется для ограничения индексирования префиксов конкретными полнотекстовыми полями в режиме dict=crc. По умолчанию все поля индексируются в режиме префикса, но поскольку индексирование префиксов может влиять как на производительность индексирования, так и на поиск, может потребоваться ограничить его определёнными полями.
Чтобы ограничить индексирование префиксов конкретными полями, используйте настройку prefix_fields с последующим списком имён полей, разделённых запятыми. Если prefix_fields не задан, то все поля будут индексироваться в режиме префикса.
- CONFIG
table products {
prefix_fields = title, name
min_prefix_len = 3
dict = crcinfix_fields = field1[, field2, ...]
Настройка infix_fields позволяет указать список полнотекстовых полей, для которых будет ограничено индексирование инфиксов. Это применяется только к режиму dict=crc и является необязательным, по умолчанию индексируются все поля в режиме инфикса. Эта настройка похожа на prefix_fields, но позволяет ограничить индексирование инфиксов конкретными полями.
- CONFIG
table products {
infix_fields = title, name
min_infix_len = 3
dict = crcmax_substring_len = length
Директива max_substring_len задаёт максимальную длину подстроки, которая будет индексироваться для поиска по префиксу или инфиксу. Эта настройка необязательна, и её значение по умолчанию равно 0 (что означает, что индексируются все возможные подстроки). Она применяется только к режиму dict.
По умолчанию индексирование подстрок в режиме dict индексирует все возможные подстроки как отдельные ключевые слова, что может привести к чрезмерно большому полнотекстовому индексу. Поэтому директива max_substring_len позволяет пропускать слишком длинные подстроки, которые, вероятно, никогда не будут искаться.
Например, тестовая таблица из 10 000 блог-постов занимает разное количество дискового пространства в зависимости от настроек:
- 6.4 МБ базовый уровень (без подстрок)
- 24.3 МБ (3.8x) с min_prefix_len = 3
- 22.2 МБ (3.5x) с min_prefix_len = 3, max_substring_len = 8
- 19.3 МБ (3.0x) с min_prefix_len = 3, max_substring_len = 6
- 94.3 МБ (14.7x) с min_infix_len = 3
- 84.6 МБ (13.2x) с min_infix_len = 3, max_substring_len = 8
- 70.7 МБ (11.0x) с min_infix_len = 3, max_substring_len = 6
Таким образом, ограничение максимальной длины подстроки может сэкономить 10-15% размера таблицы.
При использовании режима dict=keywords влияние длины подстроки на производительность отсутствует. Поэтому эта директива не применяется и намеренно запрещена в этом случае. Однако при необходимости вы всё равно можете ограничить длину подстроки, которую ищете, в коде приложения.
- CONFIG
table products {
max_substring_len = 12
min_infix_len = 3
dict = crcexpand_keywords = {0|1|exact|star}
Эта настройка расширяет ключевые слова их точными формами и/или со звёздочками, когда это возможно. Поддерживаемые значения:
- 1 - расширять и точной формой, и формой со звёздочками. Например,
runningстанет(running | *running* | =running) exact- расширять ключевое слово только точной формой. Например,runningстанет(running | =running)star- расширять ключевое слово, добавляя*вокруг него. Например,runningстанет(running | *running*)Эта настройка необязательна, значение по умолчанию — 0 (ключевые слова не расширяются).
Запросы к таблицам с включённой функцией expand_keywords внутренне расширяются следующим образом: если таблица была построена с включённым индексированием префиксов или инфиксов, каждое ключевое слово внутренне заменяется дизъюнкцией самого ключевого слова и соответствующего префикса или инфикса (ключевое слово со звёздочками). Если таблица была построена с включённым стеммингом и index_exact_words, также добавляется точная форма.
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) expand_keywords = '1'POST /cli -d "
CREATE TABLE products(title text, price float) expand_keywords = '1'"$index = new \Manticoresearch\Index($client);
$index->setName('products');
$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'expand_keywords' => '1'
]);utilsApi.sql('CREATE TABLE products(title text, price float) expand_keywords = \'1\'')await utilsApi.sql('CREATE TABLE products(title text, price float) expand_keywords = \'1\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) expand_keywords = \'1\'');utilsApi.sql("CREATE TABLE products(title text, price float) expand_keywords = '1'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) expand_keywords = '1'", true);utils_api.sql("CREATE TABLE products(title text, price float) expand_keywords = '1'", Some(true)).await;table products {
expand_keywords = 1
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}Расширенные запросы, естественно, выполняются дольше, но могут улучшить качество поиска, так как документы с точными совпадениями форм обычно ранжируются выше, чем документы с совпадениями по стеммам или инфиксам.
Обратите внимание, что существующий синтаксис запросов не позволяет эмулировать такое расширение, поскольку внутреннее расширение работает на уровне ключевых слов и расширяет ключевые слова внутри операторов фраз и кворума тоже (что невозможно через синтаксис запросов). Посмотрите на примеры и как expand_keywords влияет на веса результатов поиска и как "runsy" находится по запросу "runs" без необходимости добавлять звёздочку:
- expand_keywords_enabled
- expand_keywords_disabled
mysql> create table t(f text) min_infix_len='2' expand_keywords='1' morphology='stem_en';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> insert into t values(1,'running'),(2,'runs'),(3,'runsy');
Query OK, 3 rows affected (0.00 sec)
mysql> select *, weight() from t where match('runs');
+------+---------+----------+
| id | f | weight() |
+------+---------+----------+
| 2 | runs | 1560 |
| 1 | running | 1500 |
| 3 | runsy | 1500 |
+------+---------+----------+
3 rows in set (0.01 sec)
mysql> drop table t;
Query OK, 0 rows affected (0.01 sec)
mysql> create table t(f text) min_infix_len='2' expand_keywords='exact' morphology='stem_en';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> insert into t values(1,'running'),(2,'runs'),(3,'runsy');
Query OK, 3 rows affected (0.00 sec)
mysql> select *, weight() from t where match('running');
+------+---------+----------+
| id | f | weight() |
+------+---------+----------+
| 1 | running | 1590 |
| 2 | runs | 1500 |
+------+---------+----------+
2 rows in set (0.00 sec)mysql> create table t(f text) min_infix_len='2' morphology='stem_en';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> insert into t values(1,'running'),(2,'runs'),(3,'runsy');
Query OK, 3 rows affected (0.00 sec)
mysql> select *, weight() from t where match('runs');
+------+---------+----------+
| id | f | weight() |
+------+---------+----------+
| 1 | running | 1500 |
| 2 | runs | 1500 |
+------+---------+----------+
2 rows in set (0.00 sec)
mysql> drop table t;
Query OK, 0 rows affected (0.01 sec)
mysql> create table t(f text) min_infix_len='2' morphology='stem_en';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> insert into t values(1,'running'),(2,'runs'),(3,'runsy');
Query OK, 3 rows affected (0.00 sec)
mysql> select *, weight() from t where match('running');
+------+---------+----------+
| id | f | weight() |
+------+---------+----------+
| 1 | running | 1500 |
| 2 | runs | 1500 |
+------+---------+----------+
2 rows in set (0.00 sec)This directive does not affect indexer in any way, it only affects searchd.
expansion_limit = number
Максимальное количество расширенных ключевых слов для одного шаблона с подстановочными знаками. Подробнее здесь.
Стоп-слова — это слова, которые игнорируются при индексировании и поиске, обычно из-за их высокой частоты и низкой значимости для результатов поиска.
Manticore Search по умолчанию применяет стемминг к стоп-словам, что может приводить к нежелательным результатам, но это можно отключить с помощью параметра stopwords_unstemmed.
Небольшие файлы стоп-слов хранятся в заголовке таблицы, и существует ограничение на размер файлов, которые могут быть встроены, определяемое опцией embedded_limit.
Стоп-слова не индексируются, но они влияют на позиции ключевых слов. Например, если "the" является стоп-словом, и документ 1 содержит фразу "in office", а документ 2 — фразу "in the office", поиск точной фразы "in office" вернёт только первый документ, даже несмотря на то, что "the" пропускается как стоп-слово во втором документе. Это поведение можно изменить с помощью директивы stopword_step.
stopwords=path/to/stopwords/file[ path/to/another/file ...]
Параметр stopwords является необязательным и по умолчанию пуст. Он позволяет указать путь к одному или нескольким файлам стоп-слов, разделённым пробелами. Все файлы будут загружены. В режиме реального времени разрешены только абсолютные пути.
Формат файла стоп-слов — простой текст с кодировкой UTF-8. Данные файла будут токенизироваться с учётом настроек charset_table, поэтому можно использовать те же разделители, что и в индексируемых данных.
Файлы стоп-слов можно создавать вручную или полуавтоматически. Индексатор предоставляет режим, который создаёт частотный словарь таблицы, отсортированный по частоте ключевых слов. Верхние ключевые слова из этого словаря обычно можно использовать как стоп-слова. Подробнее см. переключатели --buildstops и --buildfreqs. Верхние ключевые слова из этого словаря обычно можно использовать как стоп-слова.
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) stopwords = '/usr/local/manticore/data/stopwords.txt /usr/local/manticore/data/stopwords-ru.txt /usr/local/manticore/data/stopwords-en.txt'POST /cli -d "
CREATE TABLE products(title text, price float) stopwords = '/usr/local/manticore/data/stopwords.txt stopwords-ru.txt stopwords-en.txt'"$index = new \Manticoresearch\Index($client);
$index->setName('products');
$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'stopwords' => '/usr/local/manticore/data/stopwords.txt stopwords-ru.txt stopwords-en.txt'
]);utilsApi.sql('CREATE TABLE products(title text, price float) stopwords = \'/usr/local/manticore/data/stopwords.txt /usr/local/manticore/data/stopwords-ru.txt /usr/local/manticore/data/stopwords-en.txt\'')await utilsApi.sql('CREATE TABLE products(title text, price float) stopwords = \'/usr/local/manticore/data/stopwords.txt /usr/local/manticore/data/stopwords-ru.txt /usr/local/manticore/data/stopwords-en.txt\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) stopwords = \'/usr/local/manticore/data/stopwords.txt /usr/local/manticore/data/stopwords-ru.txt /usr/local/manticore/data/stopwords-en.txt\'');utilsApi.sql("CREATE TABLE products(title text, price float) stopwords = '/usr/local/manticore/data/stopwords.txt /usr/local/manticore/data/stopwords-ru.txt /usr/local/manticore/data/stopwords-en.txt'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) stopwords = '/usr/local/manticore/data/stopwords.txt /usr/local/manticore/data/stopwords-ru.txt /usr/local/manticore/data/stopwords-en.txt'", true);utils_api.sql("CREATE TABLE products(title text, price float) stopwords = '/usr/local/manticore/data/stopwords.txt /usr/local/manticore/data/stopwords-ru.txt /usr/local/manticore/data/stopwords-en.txt'", Some(true)).await;table products {
stopwords = /usr/local/manticore/data/stopwords.txt
stopwords = stopwords-ru.txt stopwords-en.txt
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}В качестве альтернативы можно использовать один из стандартных файлов стоп-слов, поставляемых с Manticore. В настоящее время доступны стоп-слова для 50 языков. Вот полный список их псевдонимов:
- af - африкаанс
- ar - арабский
- bg - болгарский
- bn - бенгальский
- ca - каталанский
- ckb - курдский
- cz - чешский
- da - датский
- de - немецкий
- el - греческий
- en - английский
- eo - эсперанто
- es - испанский
- et - эстонский
- eu - баскский
- fa - персидский
- fi - финский
- fr - французский
- ga - ирландский
- gl - галисийский
- hi - хинди
- he - иврит
- hr - хорватский
- hu - венгерский
- hy - армянский
- id - индонезийский
- it - итальянский
- ja - японский
- ko - корейский
- la - латинский
- lt - литовский
- lv - латышский
- mr - маратхи
- nl - нидерландский
- no - норвежский
- pl - польский
- pt - португальский
- ro - румынский
- ru - русский
- sk - словацкий
- sl - словенский
- so - сомалийский
- st - сото
- sv - шведский
- sw - суахили
- th - тайский
- tr - турецкий
- yo - йоруба
- zh - китайский
- zu - зулу
Например, чтобы использовать стоп-слова для итальянского языка, просто добавьте следующую строку в ваш конфигурационный файл:
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) stopwords = 'it'POST /cli -d "
CREATE TABLE products(title text, price float) stopwords = 'it'"$index = new \Manticoresearch\Index($client);
$index->setName('products');
$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'stopwords' => 'it'
]);utilsApi.sql('CREATE TABLE products(title text, price float) stopwords = \'it\'')await utilsApi.sql('CREATE TABLE products(title text, price float) stopwords = \'it\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) stopwords = \'it\'');utilsApi.sql("CREATE TABLE products(title text, price float) stopwords = 'it'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) stopwords = 'it'", true);utils_api.sql("CREATE TABLE products(title text, price float) stopwords = 'it'", Some(true)).await;table products {
stopwords = it
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}Если необходимо использовать стоп-слова для нескольких языков, перечислите все их псевдонимы, разделённые запятыми (в режиме RT) или пробелами (в обычном режиме):
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) stopwords = 'en, it, ru'POST /cli -d "
CREATE TABLE products(title text, price float) stopwords = 'en, it, ru'"$index = new \Manticoresearch\Index($client);
$index->setName('products');
$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'stopwords' => 'en, it, ru'
]);utilsApi.sql('CREATE TABLE products(title text, price float) stopwords = \'en, it, ru\'')await utilsApi.sql('CREATE TABLE products(title text, price float) stopwords = \'en, it, ru\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) stopwords = \'en, it, ru\'');utilsApi.sql("CREATE TABLE products(title text, price float) stopwords = 'en, it, ru'", true);utilsApi.sql("CREATE TABLE products(title text, price float) stopwords = 'en, it, ru'", true);utils_api.sql("CREATE TABLE products(title text, price float) stopwords = 'en, it, ru'", Some(true)).await;table products {
stopwords = en it ru
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}stopword_step={0|1}
Параметр position_increment в stopwords является необязательным, допустимые значения — 0 и 1, по умолчанию 1.
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) stopwords = 'en' stopword_step = '1'POST /cli -d "
CREATE TABLE products(title text, price float) stopwords = 'en' stopword_step = '1'"$index = new \Manticoresearch\Index($client);
$index->setName('products');
$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'stopwords' => 'en, it, ru',
'stopword_step' => '1'
]);utilsApi.sql('CREATE TABLE products(title text, price float) stopwords = \'en\' stopword_step = \'1\'')await utilsApi.sql('CREATE TABLE products(title text, price float) stopwords = \'en\' stopword_step = \'1\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) stopwords = \'en\' stopword_step = \'1\'');utilsApi.sql("CREATE TABLE products(title text, price float) stopwords = \'en\' stopword_step = \'1\'", true);utilsApi.sql("CREATE TABLE products(title text, price float) stopwords = \'en\' stopword_step = \'1\'", true);utils_api.sql("CREATE TABLE products(title text, price float) stopwords = \'en\' stopword_step = \'1\'", Some(true)).await;table products {
stopwords = en
stopword_step = 1
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}stopwords_unstemmed={0|1}
Whether to apply stop words before or after stemming. Optional, default is 0 (apply stop word filter after stemming).
By default, stop words are stemmed themselves, and then applied to tokens after stemming (or any other morphology processing). This means that a token is stopped when stem(token) is equal to stem(stopword). This default behavior can lead to unexpected results when a token is erroneously stemmed to a stopped root. For example, "Andes" might get stemmed to "and", so when "and" is a stopword, "Andes" is also skipped.
However, you can change this behavior by enabling the stopwords_unstemmed directive. When this is enabled, stop words are applied before stemming (and therefore to the original word forms), and the tokens are skipped when the token is equal to the stopword.
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) stopwords = 'en' stopwords_unstemmed = '1'POST /cli -d "
CREATE TABLE products(title text, price float) stopwords = 'en' stopwords_unstemmed = '1'"$index = new \Manticoresearch\Index($client);
$index->setName('products');
$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'stopwords' => 'en, it, ru',
'stopwords_unstemmed' => '1'
]);utilsApi.sql('CREATE TABLE products(title text, price float) stopwords = \'en\' stopwords_unstemmed = \'1\'')await utilsApi.sql('CREATE TABLE products(title text, price float) stopwords = \'en\' stopwords_unstemmed = \'1\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) stopwords = \'en\' stopwords_unstemmed = \'1\'');utilsApi.sql("CREATE TABLE products(title text, price float) stopwords = \'en\' stopwords_unstemmed = \'1\'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) stopwords = \'en\' stopwords_unstemmed = \'1\'", true);utils_api.sql("CREATE TABLE products(title text, price float) stopwords = \'en\' stopwords_unstemmed = \'1\'", Some(true)).await;table products {
stopwords = en
stopwords_unstemmed = 1
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}Формы слов применяются после токенизации входящего текста по правилам charset_table. Они по сути позволяют заменить одно слово другим. Обычно это используется для приведения различных форм слова к одной нормальной форме (например, нормализация всех вариантов таких как "walks", "walked", "walking" к нормальной форме "walk"). Также это может использоваться для реализации исключений стемминга, поскольку стемминг не применяется к словам, найденным в списке форм.
wordforms = path/to/wordforms.txt
wordforms = path/to/alternateforms.txt
wordforms = path/to/dict*.txt
Словарь форм слов. Опционально, по умолчанию пустой.
Словари форм слов используются для нормализации входящих слов как при индексации, так и при поиске. Поэтому, когда речь идет о plain table, требуется выполнить ротацию таблицы, чтобы применить изменения в файле форм слов.
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) wordforms = '/var/lib/manticore/wordforms.txt' wordforms = '/var/lib/manticore/alternateforms.txt /var/lib/manticore/dict*.txt'POST /cli -d "
CREATE TABLE products(title text, price float) wordforms = '/var/lib/manticore/wordforms.txt' wordforms = '/var/lib/manticore/alternateforms.txt' wordforms = '/var/lib/manticore/dict*.txt'"$index = new \Manticoresearch\Index($client);
$index->setName('products');
$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'wordforms' => [
'/var/lib/manticore/wordforms.txt',
'/var/lib/manticore/alternateforms.txt',
'/var/lib/manticore/dict*.txt'
]
]);utilsApi.sql('CREATE TABLE products(title text, price float) wordforms = \'/var/lib/manticore/wordforms.txt\' wordforms = \'/var/lib/manticore/alternateforms.txt\' wordforms = \'/var/lib/manticore/dict*.txt\'')await utilsApi.sql('CREATE TABLE products(title text, price float) wordforms = \'/var/lib/manticore/wordforms.txt\' wordforms = \'/var/lib/manticore/alternateforms.txt\' wordforms = \'/var/lib/manticore/dict*.txt\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float)wordforms = \'/var/lib/manticore/wordforms.txt\' wordforms = \'/var/lib/manticore/alternateforms.txt\' wordforms = \'/var/lib/manticore/dict*.txt\'');utilsApi.sql("CREATE TABLE products(title text, price float) wordforms = '/var/lib/manticore/wordforms.txt' wordforms = '/var/lib/manticore/alternateforms.txt' wordforms = '/var/lib/manticore/dict*.txt'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) wordforms = '/var/lib/manticore/wordforms.txt' wordforms = '/var/lib/manticore/alternateforms.txt' wordforms = '/var/lib/manticore/dict*.txt'", true);utils_api.sql("CREATE TABLE products(title text, price float) wordforms = '/var/lib/manticore/wordforms.txt' wordforms = '/var/lib/manticore/alternateforms.txt' wordforms = '/var/lib/manticore/dict*.txt'", Some(true)).await;table products {
wordforms = /var/lib/manticore/wordforms.txt
wordforms = /var/lib/manticore/alternateforms.txt
wordforms = /var/lib/manticore/dict*.txt
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}Поддержка форм слов в Manticore разработана для эффективной работы с большими словарями. Они умеренно влияют на скорость индексации; например, словарь с 1 миллионом записей замедляет полнотекстовую индексацию примерно в 1.5 раза. Скорость поиска при этом не страдает. Дополнительное потребление RAM примерно равно размеру файла словаря, и словари разделяются между таблицами. Например, если один и тот же файл форм слов размером 50 МБ указан для 10 разных таблиц, дополнительное потребление RAM searchd будет около 50 МБ.
Файл словаря должен быть в простом текстовом формате. Каждая строка должна содержать исходную и целевую формы слова в кодировке UTF-8, разделённые знаком "больше" (>). Правила из charset_table будут применены при загрузке файла. Поэтому, если вы не изменяете charset_table, ваши формы слов будут нечувствительны к регистру, как и остальные данные, индексируемые полнотекстово. Ниже приведён пример содержимого файла:
- Example
walks > walk
walked > walk
walking > walkВ комплекте есть утилита Spelldump, которая помогает создать файл словаря в формате, читаемом Manticore. Утилита может читать исходные файлы словарей .dict и .aff в формате ispell или MySpell, как в комплекте с OpenOffice.
Вы можете сопоставить несколько исходных слов с одним целевым словом. Процесс происходит на уровне токенов, а не исходного текста, поэтому различия в пробелах и разметке игнорируются.
Вы можете использовать символ => вместо >. Также допускаются комментарии (начинающиеся с #). Наконец, если строка начинается с тильды (~), форма слова будет применена после морфологии, а не до (обратите внимание, что в этом случае поддерживается только одно исходное и одно целевое слово).
- Example
core 2 duo > c2d
e6600 > c2d
core 2duo => c2d # Some people write '2duo' together...
~run > walk # Along with stem_en morphology enabled replaces 'run', 'running', 'runs' (and any other words that stem to just 'run') to 'walk'Если вам нужно использовать >, = или ~ как обычные символы, вы можете экранировать их, предваряя обратным слэшем (\). И >, и = должны быть экранированы таким образом. Вот пример:
- Example
a\> > abc
\>b > bcd
c\=\> => cde
\=\>d => def
\=\>a \> f \> => foo
\~g => barВы можете указать несколько целевых токенов:
- Example
s02e02 > season 2 episode 2
s3 e3 > season 3 episode 3Вы можете указать несколько файлов, а не только один. Маски могут использоваться как шаблоны, и все подходящие файлы будут обработаны в простом порядке возрастания:
В режиме RT допускаются только абсолютные пути.
Если используются многобайтовые кодировки и имена файлов содержат нелатинские символы, итоговый порядок может быть не совсем алфавитным. Если одно и то же определение формы слова встречается в нескольких файлах, используется последнее, переопределяющее предыдущие.
- SQL
- Config
create table tbl1 ... wordforms='/tmp/wf*'
create table tbl2 ... wordforms='/tmp/wf, /tmp/wf2'wordforms=/tmp/wf
wordforms=/tmp/wf2
wordforms=/tmp/wf_new*Исключения (также известные как синонимы) позволяют сопоставлять один или несколько токенов (включая токены с символами, которые обычно исключаются) с одним ключевым словом. Они похожи на wordforms тем, что также выполняют сопоставление, но имеют ряд важных отличий.
Краткое резюме отличий от wordforms следующее:
| Исключения | Формы слов |
|---|---|
| Чувствительны к регистру | Не чувствительны к регистру |
| Могут использовать специальные символы, отсутствующие в charset_table | Полностью подчиняются charset_table |
| Плохо работают с огромными словарями | Предназначены для обработки миллионов записей |
exceptions = path/to/exceptions.txt
Файл исключений для токенизации. Необязательный, по умолчанию пустой. В режиме RT допускаются только абсолютные пути.
Ожидаемый формат файла — простой текст, по одному исключению на строку. Формат строки следующий:
map-from-tokens => map-to-token
Пример файла:
at & t => at&t
AT&T => AT&T
Standarten Fuehrer => standartenfuhrer
Standarten Fuhrer => standartenfuhrer
MS Windows => ms windows
Microsoft Windows => ms windows
C++ => cplusplus
c++ => cplusplus
C plus plus => cplusplus
\=\>abc\> => abc
Все токены здесь чувствительны к регистру и не будут обрабатываться правилами charset_table. Таким образом, с приведённым выше примером файла исключений, текст at&t будет токенизирован как два ключевых слова at и t из-за строчных букв. С другой стороны, AT&T будет точно совпадать и породит одно ключевое слово AT&T.
Если вам нужно использовать > или = как обычные символы, вы можете экранировать их, предваряя каждый обратным слэшем (\). И >, и = должны быть экранированы таким образом.
Обратите внимание, что ключевые слова для сопоставления:
- всегда интерпретируются как одно слово
- чувствительны к регистру и пробелам
В приведённом выше примере запрос ms windows не совпадёт с документом, содержащим текст MS Windows. Запрос будет интерпретирован как запрос по двум ключевым словам, ms и windows. Сопоставление для MS Windows — это одно ключевое слово ms windows с пробелом посередине. С другой стороны, standartenfuhrer найдёт документы с содержимым Standarten Fuhrer или Standarten Fuehrer (с точным таким же регистром), или любую вариацию регистра самого ключевого слова, например, staNdarTenfUhreR. (Однако он не найдёт standarten fuhrer: этот текст не совпадает ни с одним из перечисленных исключений из-за чувствительности к регистру и индексируется как два отдельных ключевых слова.)
Пробелы в списке токенов для сопоставления важны, но их количество — нет. Любое количество пробелов в списке для сопоставления будет соответствовать любому другому количеству пробелов в индексированном документе или запросе. Например, токен для сопоставления AT & T будет соответствовать тексту AT & T, независимо от количества пробелов как в части для сопоставления, так и в индексированном тексте. Такой текст, следовательно, будет индексироваться как специальное ключевое слово AT&T, благодаря самой первой записи из примера.
Исключения также позволяют захватывать специальные символы (которые являются исключениями из общих правил charset_table; отсюда и название). Предположим, что вы обычно не хотите рассматривать + как допустимый символ, но всё же хотите иметь возможность искать некоторые исключения из этого правила, например, C++. Приведённый выше пример сделает именно это, полностью независимо от того, какие символы есть в таблице, а каких нет.
При использовании plain table необходимо вращать таблицу, чтобы учесть изменения из файла исключений. В случае таблицы реального времени изменения будут применяться только к новым документам.
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) exceptions = '/usr/local/manticore/data/exceptions.txt'POST /cli -d "
CREATE TABLE products(title text, price float) exceptions = '/usr/local/manticore/data/exceptions.txt'"$index = new \Manticoresearch\Index($client);
$index->setName('products');
$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'exceptions' => '/usr/local/manticore/data/exceptions.txt'
]);utilsApi.sql('CREATE TABLE products(title text, price float) exceptions = \'/usr/local/manticore/data/exceptions.txt\'')await utilsApi.sql('CREATE TABLE products(title text, price float) exceptions = \'/usr/local/manticore/data/exceptions.txt\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) exceptions = \'/usr/local/manticore/data/exceptions.txt\'');utilsApi.sql("CREATE TABLE products(title text, price float) exceptions = '/usr/local/manticore/data/exceptions.txt'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) exceptions = '/usr/local/manticore/data/exceptions.txt'", true);utils_api.sql("CREATE TABLE products(title text, price float) exceptions = '/usr/local/manticore/data/exceptions.txt'", Some(true)).await;table products {
exceptions = /usr/local/manticore/data/exceptions.txt
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}