Когда текст индексируется в Manticore, он разбивается на слова, и выполняется преобразование регистра, чтобы такие слова, как "Abc", "ABC" и "abc", рассматривались как одно и то же слово.
Для правильного выполнения этих операций Manticore должен знать:
- кодировку исходного текста (которая всегда должна быть UTF-8)
- какие символы считаются буквами, а какие нет
- какие буквы должны преобразовываться в другие буквы
Вы можете настроить эти параметры для каждой таблицы отдельно, используя опцию charset_table. charset_table задаёт массив, который отображает буквенные символы в их версии с приведённым регистром (или в любые другие символы по вашему выбору). Символы, отсутствующие в массиве, считаются не буквами и будут рассматриваться как разделители слов при индексировании или поиске в этой таблице.
По умолчанию используется набор символов non_cont, который включает большинство языков.
Вы также можете определить правила замены текстовых шаблонов. Например, с помощью следующих правил:
regexp_filter = \**(\d+)\" => \1 inch
regexp_filter = (BLUE|RED) => COLOR
Текст RED TUBE 5" LONG будет индексироваться как COLOR TUBE 5 INCH LONG, а PLANK 2" x 4" будет индексироваться как PLANK 2 INCH x 4 INCH. Эти правила применяются в указанном порядке. Правила также применяются к запросам, поэтому поиск по BLUE TUBE фактически будет искать COLOR TUBE.
Подробнее о regexp_filter можно узнать здесь.
# default
charset_table = non_cont
# only English and Russian letters
charset_table = 0..9, A..Z->a..z, _, a..z, \
U+410..U+42F->U+430..U+44F, U+430..U+44F, U+401->U+451, U+451
# english charset defined with alias
charset_table = 0..9, english, _
# you can override character mappings by redefining them, e.g. for case insensitive search with German umlauts you can use:
charset_table = non_cont, U+00E4, U+00C4->U+00E4, U+00F6, U+00D6->U+00F6, U+00FC, U+00DC->U+00FC, U+00DF, U+1E9E->U+00DF
charset_table задаёт массив, который отображает буквенные символы в их версии с приведённым регистром (или в любые другие символы, если вы предпочитаете). По умолчанию используется набор символов non_cont, который включает большинство языков с непрерывными скриптами.
charset_table является основным элементом процесса токенизации Manticore, который извлекает ключевые слова из текста документа или текста запроса. Он контролирует, какие символы считаются допустимыми и как они должны преобразовываться (например, нужно ли убирать регистр).
По умолчанию каждый символ отображается в 0, что означает, что он не считается допустимым ключевым словом и рассматривается как разделитель. Как только символ упоминается в таблице, он отображается в другой символ (чаще всего либо в себя, либо в строчную букву) и считается допустимой частью ключевого слова.
charset_table использует список отображений, разделённых запятыми, чтобы объявить символы допустимыми или отобразить их в другие символы. Доступны сокращения для отображения диапазонов символов сразу:
- Отображение одного символа:
A->a. Объявляет исходный символ 'A' допустимым в ключевых словах и отображает его в символ 'a' (но не объявляет 'a' допустимым). - Отображение диапазона:
A..Z->a..z. Объявляет все символы в исходном диапазоне допустимыми и отображает их в символы в целевом диапазоне. Не объявляет целевой диапазон допустимым. Проверяет длины обоих диапазонов. - Отображение одиночного символа:
a. Объявляет символ допустимым и отображает его в себя. Эквивалентно отображению одного символаa->a. - Отображение одиночного диапазона:
a..z. Объявляет все символы в диапазоне допустимыми и отображает их в себя. Эквивалентно отображению диапазонаa..z->a..z. - Отображение с шагом 2:
A..Z/2. Отображает каждую пару символов во второй символ. Например,A..Z/2эквивалентноA->B, B->B, C->D, D->D, ..., Y->Z, Z->Z. Это сокращение полезно для блоков Unicode, где заглавные и строчные буквы идут в перемешку.
Для символов с кодами от 0 до 32, а также для символов в диапазоне от 127 до 8-битных ASCII и Unicode, Manticore всегда рассматривает их как разделители. Чтобы избежать проблем с кодировкой в конфигурационных файлах, 8-битные ASCII символы и Unicode символы должны указываться в форме U+XXX, где XXX — это шестнадцатеричный номер кода символа. Минимально допустимый код символа Unicode — U+0021.
Если стандартных отображений недостаточно, вы можете переопределить отображения символов, указав их заново с другим отображением. Например, если встроенный массив non_cont включает символы Ä и ä и отображает их обоих в ASCII символ a, вы можете переопределить эти символы, добавив их коды Unicode, например так:
charset_table = non_cont,U+00E4,U+00C4
для поиска с учётом регистра или
charset_table = non_cont,U+00E4,U+00C4->U+00E4
для поиска без учёта регистра.
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) charset_table = '0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F, U+401->U+451, U+451'POST /cli -d "
CREATE TABLE products(title text, price float) charset_table = '0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F, U+401->U+451, U+451'"$index = new \Manticoresearch\Index($client);
$index->setName('products');
$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'charset_table' => '0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F, U+401->U+451, U+451'
]);utilsApi.sql('CREATE TABLE products(title text, price float) charset_table = \'0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F, U+401->U+451, U+451\'')await utilsApi.sql('CREATE TABLE products(title text, price float) charset_table = \'0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F, U+401->U+451, U+451\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) charset_table = \'0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F, U+401->U+451, U+451\'');utilsApi.sql("CREATE TABLE products(title text, price float) charset_table = '0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F, U+401->U+451, U+451'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) charset_table = '0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F, U+401->U+451, U+451'", true);utils_api.sql("CREATE TABLE products(title text, price float) charset_table = '0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F, U+401->U+451, U+451'", Some(true)).await;table products {
charset_table = 0..9, A..Z->a..z, _, a..z, \
U+410..U+42F->U+430..U+44F, U+430..U+44F, U+401->U+451, U+451
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}Помимо определения символов и отображений, доступны несколько встроенных псевдонимов, которые можно использовать. Текущие псевдонимы:
chinesecjkcontenglishjapanesekoreannon_cont(non_cjk)russianthai
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) charset_table = '0..9, english, _'POST /cli -d "
CREATE TABLE products(title text, price float) charset_table = '0..9, english, _'"$index = new \Manticoresearch\Index($client);
$index->setName('products');
$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'charset_table' => '0..9, english, _'
]);utilsApi.sql('CREATE TABLE products(title text, price float) charset_table = \'0..9, english, _\'')await utilsApi.sql('CREATE TABLE products(title text, price float) charset_table = \'0..9, english, _\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) charset_table = \'0..9, english, _\'');utilsApi.sql("CREATE TABLE products(title text, price float) charset_table = '0..9, english, _'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) charset_table = '0..9, english, _'", true);utils_api.sql("CREATE TABLE products(title text, price float) charset_table = '0..9, english, _'", Some(true)).await;table products {
charset_table = 0..9, english, _
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}Если вы хотите поддерживать разные языки в поиске, определение наборов допустимых символов и правил свёртки для всех из них может быть трудоёмкой задачей. Мы упростили это для вас, предоставив таблицы символов по умолчанию — non_cont и cont, которые охватывают языки с прерывистыми и непрерывными (китайский, японский, корейский, тайский) письменностями соответственно. В большинстве случаев этих наборов символов будет достаточно для ваших нужд.
Обратите внимание, что следующие языки в настоящее время не поддерживаются:
- Assamese
- Bishnupriya
- Buhid
- Garo
- Hmong
- Ho
- Komi
- Large Flowery Miao
- Maba
- Maithili
- Marathi
- Mende
- Mru
- Myene
- Ngambay
- Odia
- Santali
- Sindhi
- Sylheti
Все остальные языки, перечисленные в списке языков Unicode, поддерживаются по умолчанию. Чтобы работать как с языками с непрерывной, так и с прерывистой письменностью, установите параметры в вашем конфигурационном файле, как показано ниже (с исключением для китайского):
CREATE TABLE products(title text, price float) charset_table = 'non_cont' ngram_len = '1' ngram_chars = 'cont'
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
POST /cli -d "CREATE TABLE products(title text, price float) charset_table = 'non_cont' ngram_len = '1' ngram_chars = 'cont'"
$index = new \Manticoresearch\Index($client);$index->setName('products');
$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'charset_table' => 'non_cont',
'ngram_len' => '1',
'ngram_chars' => 'cont'
]);
##### Python:##### Python-asyncio:##### Javascript:##### java:##### C#:##### Rust:table products { charset_table = non_cont
ngram_len = 1
ngram_chars = cont
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}
Если вам не нужна поддержка языков с непрерывной письменностью, вы можете просто исключить параметры %ngram_len [../../Creating_a_table/NLP_and_tokenization/Low-level_tokenization.md#ngram_len] % и %ngram_chars [../../Creating_a_table/NLP_and_tokenization/Low-level_tokenization.md#ngram_chars] %. Для получения дополнительной информации об этих параметрах обратитесь к соответствующим разделам документации.Для отображения одного символа в несколько символов или наоборот может быть полезен regexp_filter.
blend_chars = +, &, U+23
blend_chars = +, &->+
Список смешанных символов. Необязательно, по умолчанию пусто.
Смешанные символы индексируются как разделители и как допустимые символы. Например, если `&` определён как смешанный символ и в индексируемом документе встречается `AT&T`, будут проиндексированы три разных ключевых слова: `at&t`, `at` и `t`.
Кроме того, смешанные символы могут влиять на индексацию так, что ключевые слова индексируются так, как будто смешанные символы вообще не были введены. Такое поведение особенно заметно при указании blend_mode = trim_all. Например, фраза some_thing будет индексироваться как some, something и thing при blend_mode = trim_all.
При использовании смешанных символов следует быть осторожным, так как определение символа как смешанного означает, что он больше не является разделителем.
-
Поэтому, если вы добавите запятую в
blend_charsи выполните поиск поdog,cat, это будет рассматриваться как один токенdog,cat. Еслиdog,catне был проиндексирован какdog,cat, а остался какdog cat, совпадения не будет. -
Следовательно, это поведение следует контролировать с помощью настройки blend_mode. Позиции для токенов, полученных заменой смешанных символов на пробелы, назначаются как обычно, и обычные ключевые слова индексируются так, как если бы
blend_charsвообще не было. Дополнительный токен, смешивающий смешанные и несмешанные символы, будет помещён на начальную позицию. Например, если в самом начале текстового поля встречаетсяAT&T company,atполучит позицию 1,t— позицию 2,company— позицию 3, аAT&Tтакже получит позицию 1, смешиваясь с открывающим обычным ключевым словом. В результате запросыAT&Tили простоATнайдут этот документ. Фразовый запрос"AT T"также совпадёт, как и фразовый запрос"AT&T company". Смешанные символы могут пересекаться со специальными символами, используемыми в синтаксисе запросов, такими какT-Mobileили@twitter. По возможности парсер запросов будет обрабатывать смешанный символ как смешанный. Например, еслиhello @twitterнаходится в кавычках (оператор фразы), парсер запросов обработает символ@как смешанный. Однако если символ@не в кавычках, он будет обработан как оператор. Поэтому рекомендуется экранировать ключевые слова.
Смешанные символы могут быть переназначены так, чтобы несколько разных смешанных символов нормализовались в одну базовую форму. Это полезно при индексации нескольких альтернативных кодовых точек Unicode с эквивалентными глифами.
CREATE TABLE products(title text, price float) blendchars = '+, &, U+23, @->'
POST /cli -d "
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) blend_chars = '+, &, U+23, @->_'"$index = new \Manticoresearch\Index($client);
$index->setName('products');$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'blend_chars' => '+, &, U+23, @->_'
]);
##### Python:
utilsApi.sql('CREATE TABLE products(title text, price float) blend_chars = \'+, &, U+23, @->_\'')await utilsApi.sql('CREATE TABLE products(title text, price float) blend_chars = \'+, &, U+23, @->_\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) blend_chars = \'+, &, U+23, @->_\'');utilsApi.sql("CREATE TABLE products(title text, price float) blend_chars = '+, &, U+23, @->_'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) blend_chars = '+, &, U+23, @->_'", true);utils_api.sql("CREATE TABLE products(title text, price float) blend_chars = '+, &, U+23, @->_'", Some(true)).await; blend_chars = +, &, U+23, @->_ type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}
### blend_mode
blend_mode = option [, option [, ...]]option = trim_none | trim_head | trim_tail | trim_both | trim_all | skip_pure
Режим индексации смешанных токенов включается директивой blend_mode.
По умолчанию токены, смешивающие смешанные и несмешанные символы, индексируются полностью. Например, если в `blend_chars` включены символы @ и !, строка `@dude!` будет индексироваться как два токена: `@dude!` (со всеми смешанными символами) и `dude` (без них). В результате запрос `@dude` **не** найдёт совпадений.
blend_mode добавляет гибкости этому поведению индексации. Он принимает список опций, разделённых запятыми, каждая из которых задаёт вариант индексации токенов.
Если указано несколько опций, будет проиндексировано несколько вариантов одного и того же токена. Обычные ключевые слова (полученные из этого токена путем замены смешанных символов на разделитель) всегда индексируются.
Опции:
-
trim_none- Индексировать весь токен -
trim_head- Обрезать начальные смешанные символы и индексировать полученный токен -
trim_tail- Обрезать конечные смешанные символы и индексировать полученный токен -
trim_both- Обрезать как начальные, так и конечные смешанные символы и индексировать полученный токен -
trim_all- Обрезать начальные, конечные и средние смешанные символы и индексировать полученный токен -
skip_pure- Не индексировать токен, если он состоит только из смешанных символов Используяblend_modeс примером строки@dude!выше, настройкаblend_mode = trim_head, trim_tailприведет к индексации двух токенов:@dudeиdude!. Использованиеtrim_bothне даст эффекта, так как обрезка обоих смешанных символов приведет кdude, который уже индексируется как обычное ключевое слово. Индексация@U.S.A.сtrim_both(при условии, что точка считается смешанным символом) приведет к индексацииU.S.A. Наконец,skip_pureпозволяет игнорировать последовательности, состоящие только из смешанных символов. Например,one @@@ twoбудет индексироваться какone twoи будет соответствовать этой фразе. По умолчанию это не так, потому что полностью смешанный токен индексируется и смещает позицию второго ключевого слова. Поведение по умолчанию — индексировать весь токен, что эквивалентноblend_mode = trim_none.
Учтите, что использование режимов смешивания ограничивает поиск, даже при режиме по умолчанию trim_none, если считать . смешанным символом:
-
.dog.будет индексироваться как.dog. dog -
и вы не сможете найти его по запросу
dog.. Использование большего количества режимов увеличивает вероятность совпадения вашего ключевого слова. CREATE TABLE products(title text, price float) blend_mode = 'trim_tail, skip_pure' blend_chars = '+, &'
POST /cli -d "
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) blend_mode = 'trim_tail, skip_pure' blend_chars = '+, &'"$index = new \Manticoresearch\Index($client);
$index->setName('products');$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'blend_mode' => 'trim_tail, skip_pure',
'blend_chars' => '+, &'
]);
##### Python:
utilsApi.sql('CREATE TABLE products(title text, price float) blend_mode = \'trim_tail, skip_pure\' blend_chars = \'+, &\'')await utilsApi.sql('CREATE TABLE products(title text, price float) blend_mode = \'trim_tail, skip_pure\' blend_chars = \'+, &\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) blend_mode = \'trim_tail, skip_pure\' blend_chars = \'+, &\'');utilsApi.sql("CREATE TABLE products(title text, price float) blend_mode = 'trim_tail, skip_pure' blend_chars = '+, &'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) blend_mode = 'trim_tail, skip_pure' blend_chars = '+, &'", true);utils_api.sql("CREATE TABLE products(title text, price float) blend_mode = 'trim_tail, skip_pure' blend_chars = '+, &'", Some(true)).await; blend_mode = trim_tail, skip_pure blend_chars = +, &
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}
### min_word_len
min_word_len = lengthmin_word_len — это необязательная опция конфигурации индекса в Manticore, которая задает минимальную длину индексируемого слова. Значение по умолчанию — 1, что означает, что индексируются все слова.
Индексируются только те слова, длина которых не меньше этого минимума. Например, если min_word_len равен 4, то слово 'the' индексироваться не будет, а 'they' — будет.
CREATE TABLE products(title text, price float) min_word_len = '4'
POST /cli -d "
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) min_word_len = '4'"$index = new \Manticoresearch\Index($client);
$index->setName('products');$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'min_word_len' => '4'
]);
##### Python:
utilsApi.sql('CREATE TABLE products(title text, price float) min_word_len = \'4\'')await utilsApi.sql('CREATE TABLE products(title text, price float) min_word_len = \'4\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) min_word_len = \'4\'');utilsApi.sql("CREATE TABLE products(title text, price float) min_word_len = '4'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) min_word_len = '4'", true);utils_api.sql("CREATE TABLE products(title text, price float) min_word_len = '4'", Some(true)).await; min_word_len = 4 type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}
### ngram_len
ngram_len = 1Длины N-грамм для индексирования N-граммами. Необязательно, значение по умолчанию 0 (отключить индексирование N-граммами). Известные значения — 0 и 1.
N-граммы обеспечивают базовую поддержку языков с непрерывным письмом в неразмеченных текстах. Проблема поиска в языках с непрерывным письмом заключается в отсутствии четких разделителей между словами. В некоторых случаях вы можете не захотеть использовать сегментацию на основе словаря, например, %как для китайского языка [../../Creating_a_table/NLP_and_tokenization/Languages_with_continuous_scripts.md] %. В таких случаях сегментация N-граммами может работать хорошо.
Когда эта функция включена, потоки таких языков (или любых других символов, определенных в ngram_chars) индексируются как N-граммы. Например, если входящий текст — "ABCDEF" (где A–F — символы какого-то языка), и ngram_len равен 1, он будет индексироваться как "A B C D E F". В настоящее время поддерживается только ngram_len=1. Только символы, перечисленные в таблице ngram_chars, будут разбиваться таким образом; остальные не будут затронуты.
Обратите внимание, что если поисковый запрос сегментирован, то есть между отдельными словами есть разделители, то оборачивание слов в кавычки и использование расширенного режима приведет к правильному поиску совпадений, даже если текст не был сегментирован. Например, предположим, что исходный запрос — BC DEF. После оборачивания в кавычки на стороне приложения он должен выглядеть как "BC" "DEF" (с кавычками). Этот запрос будет передан в Manticore и внутренне также разбит на 1-граммы, что даст запрос "B C" "D E F", все еще с кавычками, которые являются оператором поиска фразы. И он найдет совпадение в тексте, даже если в тексте не было разделителей.
Даже если поисковый запрос не сегментирован, Manticore должен выдавать хорошие результаты благодаря ранжированию на основе фраз: он поднимет выше совпадения фраз (что в случае N-грамм может означать более близкие совпадения многосимвольных слов).
CREATE TABLE products(title text, price float) ngram_chars = 'cont' ngram_len = '1'
POST /cli -d "
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) ngram_chars = 'cont' ngram_len = '1'"$index = new \Manticoresearch\Index($client);
$index->setName('products');$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'ngram_chars' => 'cont',
'ngram_len' => '1'
]);
##### Python:
utilsApi.sql('CREATE TABLE products(title text, price float) ngram_chars = \'cont\' ngram_len = \'1\'')await utilsApi.sql('CREATE TABLE products(title text, price float) ngram_chars = \'cont\' ngram_len = \'1\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) ngram_chars = \'cont\' ngram_len = \'1\'');utilsApi.sql("CREATE TABLE products(title text, price float) ngram_chars = 'cont' ngram_len = '1'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) ngram_chars = 'cont' ngram_len = '1'", true);utils_api.sql("CREATE TABLE products(title text, price float) ngram_chars = 'cont' ngram_len = '1'", Some(true)).await; ngram_chars = cont ngram_len = 1
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}
### ngram_chars
ngram_chars = contngram_chars = cont, U+3000..U+2FA1F
Список символов для N-грамм. Необязательно, по умолчанию пустой.
Используется вместе с параметром %ngram_len [../../Creating_a_table/NLP_and_tokenization/Low-level_tokenization.md#ngram_len] %, этот список определяет символы, последовательности которых подлежат извлечению N-грамм. Слова, состоящие из других символов, не будут затронуты функцией индексации N-грамм. Формат значения идентичен %charset_table [../../Creating_a_table/NLP_and_tokenization/Low-level_tokenization.md#charset_table] %. Символы N-грамм не могут присутствовать в %charset_table [../../Creating_a_table/NLP_and_tokenization/Low-level_tokenization.md#charset_table] %.
CREATE TABLE products(title text, price float) ngram_chars = 'U+3000..U+2FA1F' ngram_len = '1'
POST /cli -d "
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) ngram_chars = 'U+3000..U+2FA1F' ngram_len = '1'"$index = new \Manticoresearch\Index($client);
$index->setName('products');$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'ngram_chars' => 'U+3000..U+2FA1F',
'ngram_len' => '1'
]);
##### Python:
utilsApi.sql('CREATE TABLE products(title text, price float) ngram_chars = \'U+3000..U+2FA1F\' ngram_len = \'1\'')await utilsApi.sql('CREATE TABLE products(title text, price float) ngram_chars = \'U+3000..U+2FA1F\' ngram_len = \'1\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) ngram_chars = \'U+3000..U+2FA1F\' ngram_len = \'1\'');utilsApi.sql("CREATE TABLE products(title text, price float) ngram_chars = 'U+3000..U+2FA1F' ngram_len = '1'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) ngram_chars = 'U+3000..U+2FA1F' ngram_len = '1'", true);utils_api.sql("CREATE TABLE products(title text, price float) ngram_chars = 'U+3000..U+2FA1F' ngram_len = '1'", Some(true)).await; ngram_chars = U+3000..U+2FA1F ngram_len = 1
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}
Также вы можете использовать псевдоним для нашей стандартной таблицы N-грамм, как в примере. Это будет достаточно в большинстве случаев.
CREATE TABLE products(title text, price float) ngram_chars = 'cont' ngram_len = '1'POST /cli -d "
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) ngram_chars = 'cont' ngram_len = '1'"$index = new \Manticoresearch\Index($client);
$index->setName('products');$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'ngram_chars' => 'cont',
'ngram_len' => '1'
]);
##### Python:
utilsApi.sql('CREATE TABLE products(title text, price float) ngram_chars = \'cont\' ngram_len = \'1\'')await utilsApi.sql('CREATE TABLE products(title text, price float) ngram_chars = \'cont\' ngram_len = \'1\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) ngram_chars = \'cont\' ngram_len = \'1\'');utilsApi.sql("CREATE TABLE products(title text, price float) ngram_chars = 'cont' ngram_len = '1'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) ngram_chars = 'cont' ngram_len = '1'", true);utils_api.sql("CREATE TABLE products(title text, price float) ngram_chars = 'cont' ngram_len = '1'", Some(true)).await; ngram_chars = cont ngram_len = 1
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}
### ignore_chars
ignore_chars = U+ADСписок игнорируемых символов. Необязательно, по умолчанию пустой.
Полезно в случаях, когда некоторые символы, такие как мягкий перенос (U+00AD), должны не просто рассматриваться как разделители, а полностью игнорироваться. Например, если '-' просто отсутствует в charset_table, текст "abc-def" будет индексироваться как ключевые слова "abc" и "def". Напротив, если '-' добавлен в список ignore_chars, тот же текст будет индексироваться как одно ключевое слово "abcdef".
Синтаксис такой же, как для charset_table, но разрешено объявлять только символы, без их отображения. Также игнорируемые символы не должны присутствовать в charset_table.
CREATE TABLE products(title text, price float) ignore_chars = 'U+AD'
POST /cli -d "
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) ignore_chars = 'U+AD'"$index = new \Manticoresearch\Index($client);
$index->setName('products');$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'ignore_chars' => 'U+AD'
]);
##### Python:
utilsApi.sql('CREATE TABLE products(title text, price float) ignore_chars = \'U+AD\'')await utilsApi.sql('CREATE TABLE products(title text, price float) ignore_chars = \'U+AD\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) ignore_chars = \'U+AD\'');utilsApi.sql("CREATE TABLE products(title text, price float) ignore_chars = 'U+AD'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) ignore_chars = 'U+AD'", true);utils_api.sql("CREATE TABLE products(title text, price float) ignore_chars = 'U+AD'", Some(true)).await; ignore_chars = U+AD type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}
### bigram_index
bigram_index = {none|all|first_freq|both_freq}Режим индексации биграмм. Необязательно, по умолчанию отсутствует.
Индексация биграмм — это функция для ускорения поиска фраз. При индексации в индекс сохраняется список документов для всех или некоторых пар соседних слов. Этот список затем может использоваться во время поиска для значительного ускорения сопоставления фраз или подфраз.
bigram_index управляет выбором конкретных пар слов. Известные режимы:
-
all— индексировать каждую пару слов -
first_freq— индексировать только пары слов, где первое слово находится в списке частотных слов (см. bigram_freq_words). Например, приbigram_freq_words = the, in, i, aиндексация текста "alone in the dark" сохранит пары "in the" и "the dark" как биграммы, потому что они начинаются с частого слова ("in" или "the"), но "alone in" не будет индексироваться, так как "in" — второе слово в паре. -
both_freq— индексировать только пары слов, где оба слова частые. Продолжая пример, в этом режиме при индексации "alone in the dark" будет сохранена только пара "in the" (самая плохая с точки зрения поиска), остальные пары не будут индексироваться. Для большинства случаевboth_freqбудет лучшим режимом, но результаты могут варьироваться. Важно отметить, чтоbigram_indexработает только на уровне токенизации и не учитывает преобразования, такие какmorphology,wordformsилиstopwords. Это означает, что создаваемые токены очень просты, что делает поиск фраз более точным и строгим. Хотя это может улучшить точность сопоставления фраз, система становится менее способной распознавать разные формы слов или вариации их написания.
CREATE TABLE products(title text, price float) bigram_freq_words = 'the, a, you, i' bigram_index = 'both_freq'
POST /cli -d "
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) bigram_freq_words = 'the, a, you, i' bigram_index = 'both_freq'"$index = new \Manticoresearch\Index($client);
$index->setName('products');$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'bigram_freq_words' => 'the, a, you, i',
'bigram_index' => 'both_freq'
]);
##### Python:
utilsApi.sql('CREATE TABLE products(title text, price float) bigram_freq_words = \'the, a, you, i\' bigram_index = \'both_freq\'')await utilsApi.sql('CREATE TABLE products(title text, price float) bigram_freq_words = \'the, a, you, i\' bigram_index = \'both_freq\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) bigram_freq_words = \'the, a, you, i\' bigram_index = \'both_freq\'');utilsApi.sql("CREATE TABLE products(title text, price float) bigram_freq_words = 'the, a, you, i' bigram_index = 'both_freq'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) bigram_freq_words = 'the, a, you, i' bigram_index = 'both_freq'", true);utils_api.sql("CREATE TABLE products(title text, price float) bigram_freq_words = 'the, a, you, i' bigram_index = 'both_freq'", Some(true)).await; bigram_index = both_freq bigram_freq_words = the, a, you, i
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}
### bigram_freq_words
bigram_freq_words = the, a, you, iСписок ключевых слов, считающихся "частыми" при индексации биграмм. Необязательно, по умолчанию пустой.
Некоторые режимы индексации биграмм (см. %bigram_index [../../Creating_a_table/NLP_and_tokenization/Low-level_tokenization.md#bigram_index] %) требуют определения списка часто встречающихся ключевых слов. Их **не следует** путать со стоп-словами. Стоп-слова полностью исключаются как при индексации, так и при поиске. Часто встречающиеся ключевые слова используются биграммами только для определения, индексировать ли текущую пару слов или нет.
bigram_freq_words позволяет определить такой список ключевых слов.
CREATE TABLE products(title text, price float) bigram_freq_words = 'the, a, you, i' bigram_index = 'first_freq'
POST /cli -d "
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) bigram_freq_words = 'the, a, you, i' bigram_index = 'first_freq'"$index = new \Manticoresearch\Index($client);
$index->setName('products');$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'bigram_freq_words' => 'the, a, you, i',
'bigram_index' => 'first_freq'
]);
##### Python:
utilsApi.sql('CREATE TABLE products(title text, price float) bigram_freq_words = \'the, a, you, i\' bigram_index = \'first_freq\'')await utilsApi.sql('CREATE TABLE products(title text, price float) bigram_freq_words = \'the, a, you, i\' bigram_index = \'first_freq\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) bigram_freq_words = \'the, a, you, i\' bigram_index = \'first_freq\'');utilsApi.sql("CREATE TABLE products(title text, price float) bigram_freq_words = 'the, a, you, i' bigram_index = 'first_freq'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) bigram_freq_words = 'the, a, you, i' bigram_index = 'first_freq'", true);utils_api.sql("CREATE TABLE products(title text, price float) bigram_freq_words = 'the, a, you, i' bigram_index = 'first_freq'", Some(true)).await; bigram_freq_words = the, a, you, i bigram_index = first_freq
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}
### dict
dict = {keywords|crc}Тип словаря ключевых слов определяется одним из двух известных значений: 'crc' или 'keywords'. Это необязательно, по умолчанию используется 'keywords'.
Использование режима словаря ключевых слов (dict=keywords) может значительно снизить нагрузку на индексацию и обеспечить поиск подстрок в больших коллекциях. Этот режим можно использовать как для обычных, так и для RT таблиц.
CRC-словари не хранят исходный текст ключевого слова в индексе. Вместо этого они заменяют ключевые слова контрольной суммой (вычисляемой с помощью FNV64) как при поиске, так и при индексации. Это значение используется внутри индекса. Такой подход имеет два недостатка:
-
Во-первых, существует риск коллизий контрольных сумм между разными парами ключевых слов. Этот риск растет пропорционально количеству уникальных ключевых слов в индексе. Тем не менее, это незначительная проблема, так как вероятность одной коллизии FNV64 в словаре из 1 миллиарда записей примерно 1 к 16, или 6,25 процента. Большинство словарей будут содержать гораздо меньше миллиарда ключевых слов, учитывая, что типичный разговорный язык содержит от 1 до 10 миллионов словоформ.
-
Во-вторых, и что более важно, с контрольными суммами сложно выполнять поиск подстрок. Manticore решил эту проблему путем предварительной индексации всех возможных подстрок как отдельных ключевых слов (см. директивы min_prefix_len, min_infix_len). Этот метод даже имеет дополнительное преимущество — максимально быстрый поиск подстрок. Однако предварительная индексация всех подстрок значительно увеличивает размер индекса (часто в 3-10 раз и более) и, соответственно, время индексации, что делает поиск подстрок в больших индексах довольно непрактичным. Словарь ключевых слов решает обе эти проблемы. Он хранит ключевые слова в индексе и выполняет расширение подстановочных знаков во время поиска. Например, поиск по префиксу
test*может внутренне расширяться в запрос 'test|tests|testing' на основе содержимого словаря. Этот процесс расширения полностью прозрачен для приложения, за исключением того, что теперь также предоставляется отдельная статистика по каждому совпавшему ключевому слову. Для поиска подстрок (инфиксного поиска) можно использовать расширенные подстановочные знаки. Специальные символы, такие как?и%, совместимы с поиском подстрок (например,t?st*,run%,*abc*). Обратите внимание, что операторы подстановочных знаков и оператор REGEX работают только сdict=keywords.
Индексация с использованием словаря ключевых слов примерно в 1.1-1.3 раза медленнее, чем обычная индексация без подстрок, но значительно быстрее, чем индексация подстрок (префиксная или инфиксная). Размер индекса должен быть лишь немного больше, чем у стандартной таблицы без подстрок, с общей разницей в 1..10%. Время обычного поиска по ключевым словам должно быть почти одинаковым или идентичным для всех трех типов индексов (CRC без подстрок, CRC с подстроками, keywords). Время поиска подстрок может значительно варьироваться в зависимости от того, сколько ключевых слов соответствует заданной подстроке (то есть во сколько ключевых слов расширяется поисковый термин). Максимальное количество совпавших ключевых слов ограничено директивой expansion_limit.
В итоге, словари keywords и CRC предлагают два разных компромисса для поиска подстрок. Вы можете либо пожертвовать временем индексации и размером индекса ради максимально быстрого худшего случая поиска (CRC словарь), либо минимально повлиять на время индексации, но пожертвовать временем худшего случая поиска, когда префикс расширяется в большое количество ключевых слов (keywords словарь).
CREATE TABLE products(title text, price float) dict = 'keywords'
POST /cli -d "
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) dict = 'keywords'"$index = new \Manticoresearch\Index($client);
$index->setName('products');$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'dict' => 'keywords'
]);
##### Python:
utilsApi.sql('CREATE TABLE products(title text, price float) dict = \'keywords\'')await utilsApi.sql('CREATE TABLE products(title text, price float) dict = \'keywords\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) dict = \'keywords\'');utilsApi.sql("CREATE TABLE products(title text, price float) dict = 'keywords'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) dict = 'keywords'", true);utils_api.sql("CREATE TABLE products(title text, price float) dict = 'keywords'", Some(true)).await; dict = keywords type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}
### embedded_limit
embedded_limit = sizeЛимит размера встроенных исключений, словоформ или стоп-слов. Необязательно, по умолчанию 16K.
При создании таблицы вышеуказанные файлы могут быть либо сохранены внешне вместе с таблицей, либо встроены непосредственно в таблицу. Файлы размером меньше `embedded_limit` сохраняются в таблице. Для больших файлов сохраняются только имена файлов. Это также упрощает перенос файлов таблицы на другой компьютер; зачастую достаточно просто скопировать один файл.
С меньшими файлами такое встраивание уменьшает количество внешних файлов, от которых зависит таблица, и облегчает обслуживание. Но в то же время нет смысла встраивать словарь wordforms размером 100 МБ в крошечную дельта-таблицу. Поэтому необходим порог по размеру, и embedded_limit — это тот самый порог.
table products {
embedded_limit = 32K
- CONFIG
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}
### global_idf
global_idf = /path/to/global.idfПуть к файлу с глобальными (по всему кластеру) IDF ключевых слов. Необязательно, по умолчанию пусто (использовать локальные IDF).
В многотабличном кластере частоты ключевых слов, скорее всего, будут отличаться в разных таблицах. Это означает, что когда функция ранжирования использует значения на основе TF-IDF, такие как факторы семейства BM25, результаты могут ранжироваться немного по-разному в зависимости от того, на каком узле кластера они находятся.
Самый простой способ исправить эту проблему — создать и использовать глобальный словарь частот, или сокращённо глобальный IDF-файл. Эта директива позволяет указать расположение этого файла. Рекомендуется (но не обязательно) использовать расширение .idf. Когда для данной таблицы указан IDF-файл и OPTION global_idf установлен в 1, движок будет использовать частоты ключевых слов и количество документов коллекции из файла global_idf, а не только из локальной таблицы. Таким образом, IDF и значения, зависящие от них, будут оставаться согласованными по всему кластеру.
IDF-файлы могут использоваться несколькими таблицами. Только одна копия IDF-файла будет загружена searchd, даже если многие таблицы ссылаются на этот файл. Если содержимое IDF-файла изменится, новые данные можно загрузить с помощью SIGHUP.
Вы можете создать .idf файл с помощью утилиты indextool, сначала выгрузив словари с помощью переключателя --dumpdict dict.txt --stats, затем преобразовав их в формат .idf с помощью --buildidf, а затем объединив все .idf файлы по всему кластеру с помощью --mergeidf.
CREATE TABLE products(title text, price float) global_idf = '/usr/local/manticore/var/global.idf'
POST /cli -d "
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) global_idf = '/usr/local/manticore/var/global.idf'"$index = new \Manticoresearch\Index($client);
$index->setName('products');$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'global_idf' => '/usr/local/manticore/var/global.idf'
]);
##### Python:
utilsApi.sql('CREATE TABLE products(title text, price float) global_idf = \'/usr/local/manticore/var/global.idf\'')await utilsApi.sql('CREATE TABLE products(title text, price float) global_idf = \'/usr/local/manticore/var/global.idf\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) global_idf = \'/usr/local/manticore/var/global.idf\'');utilsApi.sql("CREATE TABLE products(title text, price float) global_idf = '/usr/local/manticore/var/global.idf'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) global_idf = '/usr/local/manticore/var/global.idf'", true);utils_api.sql("CREATE TABLE products(title text, price float) global_idf = '/usr/local/manticore/var/global.idf'", Some(true)).await; global_idf = /usr/local/manticore/var/global.idf type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}
### hitless_words
hitless_words = {all|path/to/file}Список слов без позиций (hitless words). Необязательно, допустимые значения — 'all' или имя файла со списком.
По умолчанию полнотекстовый индекс Manticore хранит не только список документов, соответствующих каждому ключевому слову, но и список его позиций в документе (известный как hitlist). Hitlist позволяет выполнять поиск по фразам, близости, строгому порядку и другие продвинутые типы поиска, а также ранжирование по близости фраз. Однако hitlist для некоторых часто встречающихся ключевых слов (которые по каким-то причинам нельзя исключить, несмотря на их частоту) может стать очень большим и, следовательно, замедлять обработку запросов. Кроме того, в некоторых случаях нам может быть важен только булевый поиск по ключевым словам, и позиционные операторы поиска (например, поиск по фразам) и ранжирование по фразам не нужны.
hitless_words позволяет создавать индексы, которые либо вообще не содержат позиционной информации (hitlist), либо пропускают её для определённых ключевых слов.
Индекс без позиций обычно занимает меньше места, чем соответствующий обычный полнотекстовый индекс (ожидается примерно в 1.5 раза меньше). Индексация и поиск должны быть быстрее, но при этом отсутствует поддержка позиционных запросов и ранжирования.
Если такие слова используются в позиционных запросах (например, в запросах по фразам), то слова без позиций исключаются из них и используются как операнды без позиции. Например, если "hello" и "world" — слова без позиций, а "simon" и "says" — с позициями, то фразовый запрос "simon says hello world" будет преобразован в ("simon says" & hello & world), что означает поиск "hello" и "world" в любом месте документа и точной фразы "simon says".
Позиционный запрос, содержащий только слова без позиций, приведёт к пустому узлу фразы, поэтому весь запрос вернёт пустой результат и предупреждение. Если весь словарь без позиций (используется all), то на соответствующем индексе можно использовать только булевый поиск.
CREATE TABLE products(title text, price float) hitless_words = 'all'
POST /cli -d "
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) hitless_words = 'all'"$index = new \Manticoresearch\Index($client);
$index->setName('products');$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'hitless_words' => 'all'
]);
##### Python:
utilsApi.sql('CREATE TABLE products(title text, price float) hitless_words = \'all\'')await utilsApi.sql('CREATE TABLE products(title text, price float) hitless_words = \'all\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) hitless_words = \'all\'');utilsApi.sql("CREATE TABLE products(title text, price float) hitless_words = 'all'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) hitless_words = 'all'", true);utils_api.sql("CREATE TABLE products(title text, price float) hitless_words = 'all'", Some(true)).await; hitless_words = all type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}
### index_field_lengths
index_field_lengths = {0|1}Включает вычисление и сохранение длин полей (как для каждого документа, так и средних значений по индексу) в полнотекстовом индексе. Необязательно, по умолчанию 0 (не вычислять и не сохранять).
Когда `index_field_lengths` установлен в 1, Manticore будет:
-
создавать соответствующий атрибут длины для каждого полнотекстового поля с тем же именем, но с суффиксом
__len -
вычислять длину поля (в количестве ключевых слов) для каждого документа и сохранять в соответствующий атрибут
-
вычислять средние значения по индексу. Атрибуты длины будут иметь специальный тип TOKENCOUNT, но их значения на самом деле являются обычными 32-битными целыми числами, и к ним обычно можно получить доступ. BM25A() и BM25F() функции в ранжировщике выражений основаны на этих длинах и требуют включения
index_field_lengths. Исторически Manticore использовал упрощённый, урезанный вариант BM25, который, в отличие от полной функции, не учитывал длину документа. Также поддерживается как полный вариант BM25, так и его расширение для нескольких полей, называемое BM25F. Они требуют длины на документ и длины на поле соответственно. Отсюда и дополнительная директива. CREATE TABLE products(title text, price float) index_field_lengths = '1'
POST /cli -d "
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) index_field_lengths = '1'"$index = new \Manticoresearch\Index($client);
$index->setName('products');$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'index_field_lengths' => '1'
]);
##### Python:
utilsApi.sql('CREATE TABLE products(title text, price float) index_field_lengths = \'1\'')await utilsApi.sql('CREATE TABLE products(title text, price float) index_field_lengths = \'1\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) index_field_lengths = \'1\'');utilsApi.sql("CREATE TABLE products(title text, price float) index_field_lengths = '1'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) index_field_lengths = '1'", true);utils_api.sql("CREATE TABLE products(title text, price float) index_field_lengths = '1'", Some(true)).await; index_field_lengths = 1 type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}
### index_token_filter
index_token_filter = my_lib.so:custom_blend:chars=@#&Фильтр токенов во время индексации для полнотекстового индексирования. Опционально, по умолчанию пусто.
Директива index_token_filter задаёт опциональный фильтр токенов во время индексации для полнотекстового индексирования. Эта директива используется для создания пользовательского токенизатора, который формирует токены согласно пользовательским правилам. Фильтр создаётся индексатором при индексации исходных данных в обычную таблицу или RT-таблицей при обработке операторов `INSERT` или `REPLACE`. Плагины определяются в формате `имя_библиотеки:имя_плагина:опциональная_строка_настроек`. Например, `my_lib.so:custom_blend:chars=@#&`.
CREATE TABLE products(title text, price float) index_token_filter = 'my_lib.so:custom_blend:chars=@#&' POST /cli -d "
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) index_token_filter = 'my_lib.so:custom_blend:chars=@#&'"$index = new \Manticoresearch\Index($client);
$index->setName('products');$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'index_token_filter' => 'my_lib.so:custom_blend:chars=@#&'
]);
##### Python:
utilsApi.sql('CREATE TABLE products(title text, price float) index_token_filter = \'my_lib.so:custom_blend:chars=@#&\'')await utilsApi.sql('CREATE TABLE products(title text, price float) index_token_filter = \'my_lib.so:custom_blend:chars=@#&\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) index_token_filter = \'my_lib.so:custom_blend:chars=@#&\'');utilsApi.sql("CREATE TABLE products(title text, price float) index_token_filter = 'my_lib.so:custom_blend:chars=@#&'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) index_token_filter = 'my_lib.so:custom_blend:chars=@#&'", true);utils_api.sql("CREATE TABLE products(title text, price float) index_token_filter = 'my_lib.so:custom_blend:chars=@#&'", Some(true)).await; index_token_filter = my_lib.so:custom_blend:chars=@#& type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}
### overshort_step
overshort_step = {0|1}Инкремент позиции для слишком коротких (меньше min_word_len) ключевых слов. Опционально, допустимые значения 0 и 1, по умолчанию 1.
CREATE TABLE products(title text, price float) overshort_step = '1'
POST /cli -d "
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) overshort_step = '1'"$index = new \Manticoresearch\Index($client);
$index->setName('products');$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'overshort_step' => '1'
]);
##### Python:
utilsApi.sql('CREATE TABLE products(title text, price float) overshort_step = \'1\'')utilsApi.sql('CREATE TABLE products(title text, price float) overshort_step = \'1\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) overshort_step = \'1\'');utilsApi.sql("CREATE TABLE products(title text, price float) overshort_step = '1'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) overshort_step = '1'", true);utils_api.sql("CREATE TABLE products(title text, price float) overshort_step = '1'", Some(true)).await; overshort_step = 1 type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}
### phrase_boundary
phrase_boundary = ., ?, !, U+2026 # horizontal ellipsisСписок символов границ фраз. Опционально, по умолчанию пусто.
Этот список контролирует, какие символы будут рассматриваться как границы фраз, чтобы корректировать позиции слов и включить эмуляцию поиска на уровне фраз через поиск по близости. Синтаксис похож на %charset_table [../../Creating_a_table/NLP_and_tokenization/Low-level_tokenization.md#charset_table] %, но отображения не разрешены, и символы границ не должны пересекаться с чем-либо ещё.
На границе фразы к текущей позиции слова будет добавлен дополнительный инкремент позиции слова (указанный в phrase_boundary_step). Это позволяет выполнять поиск на уровне фраз через запросы по близости: слова из разных фраз гарантированно будут находиться на расстоянии больше phrase_boundary_step друг от друга; таким образом, поиск по близости в пределах этого расстояния будет эквивалентен поиску на уровне фраз. Условие границы фразы будет срабатывать только если за таким символом следует разделитель; это сделано, чтобы избежать обработки сокращений типа S.T.A.L.K.E.R или URL как нескольких фраз. CREATE TABLE products(title text, price float) phrase_boundary = '., ?, !, U+2026' phrase_boundary_step = '10' POST /cli -d "
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) phrase_boundary = '., ?, !, U+2026' phrase_boundary_step = '10'"$index = new \Manticoresearch\Index($client);
$index->setName('products');$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'phrase_boundary' => '., ?, !, U+2026',
'phrase_boundary_step' => '10'
]);
##### Python:
utilsApi.sql('CREATE TABLE products(title text, price float) phrase_boundary = \'., ?, !, U+2026\' phrase_boundary_step = \'10\'')
await utilsApi.sql('CREATE TABLE products(title text, price float) phrase_boundary = \'., ?, !, U+2026\' phrase_boundary_step = \'10\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) phrase_boundary = \'., ?, !, U+2026\' phrase_boundary_step = \'10\'');utilsApi.sql("CREATE TABLE products(title text, price float) phrase_boundary = '., ?, !, U+2026' phrase_boundary_step = '10'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) phrase_boundary = '., ?, !, U+2026' phrase_boundary_step = '10'", true);utils_api.sql("CREATE TABLE products(title text, price float) phrase_boundary = '., ?, !, U+2026' phrase_boundary_step = '10'", Some(true)).await; phrase_boundary = ., ?, !, U+2026 phrase_boundary_step = 10
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}
### phrase_boundary_step
phrase_boundary_step = 100Инкремент позиции слова на границе фразы. Опционально, по умолчанию 0.
На границе фразы текущая позиция слова будет дополнительно увеличена на это число.
CREATE TABLE products(title text, price float) phrase_boundary_step = '100' phrase_boundary = '., ?, !, U+2026' POST /cli -d "
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) phrase_boundary_step = '100' phrase_boundary = '., ?, !, U+2026'"$index = new \Manticoresearch\Index($client);
$index->setName('products');$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'phrase_boundary_step' => '100',
'phrase_boundary' => '., ?, !, U+2026'
]);
##### Python:
utilsApi.sql('CREATE TABLE products(title text, price float) phrase_boundary_step = \'100\' phrase_boundary = \'., ?, !, U+2026\'')
await utilsApi.sql('CREATE TABLE products(title text, price float) phrase_boundary_step = \'100\' phrase_boundary = \'., ?, !, U+2026\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) phrase_boundary_step = \'100\' phrase_boundary = \'., ?, !, U+2026\'');utilsApi.sql("CREATE TABLE products(title text, price float) phrase_boundary_step = '100' phrase_boundary = '., ?, !, U+2026'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) phrase_boundary_step = '100' phrase_boundary = '., ?, !, U+2026'", true);utils_api.sql("CREATE TABLE products(title text, price float) phrase_boundary_step = '100' phrase_boundary = '., ?, !, U+2026'", Some(true)).await; phrase_boundary_step = 100 phrase_boundary = ., ?, !, U+2026
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}
### regexp_filter
# index '13"' as '13inch'regexp_filter = \b(\d+)\" => \1inch
# index 'blue' or 'red' as 'color'
regexp_filter = (blue|red) => color
Регулярные выражения (regexps), используемые для фильтрации полей и запросов. Эта директива является необязательной, может принимать несколько значений, и по умолчанию представляет собой пустой список регулярных выражений. Движок регулярных выражений, используемый в Manticore Search, — это RE2 от Google, известный своей скоростью и безопасностью. Для подробной информации о синтаксисе, поддерживаемом RE2, вы можете посетить %руководство по синтаксису RE2 [https://github.com/google/re2/wiki/Syntax] %.
В некоторых приложениях, таких как поиск товаров, может быть много способов обозначить продукт, модель или свойство. Например, `iPhone 3gs` и `iPhone 3 gs` (или даже `iPhone3 gs`) с большой вероятностью относятся к одному и тому же продукту. Другой пример — различные способы указания размера экрана ноутбука, такие как `13-inch`, `13 inch`, `13"`, или `13in`.
Регулярные выражения предоставляют механизм для задания правил, адаптированных для обработки таких случаев. В первом примере вы могли бы использовать файл wordforms для обработки нескольких моделей iPhone, но во втором примере лучше задать правила, которые нормализуют "13-inch" и "13in" к одному и тому же виду.
Регулярные выражения, перечисленные в regexp_filter, применяются в том порядке, в котором они указаны, на самом раннем этапе, до любой другой обработки (включая исключения), даже до токенизации. То есть, регулярные выражения применяются к исходным полям при индексации и к исходному тексту поискового запроса при поиске.
CREATE TABLE products(title text, price float) regexp_filter = '(blue|red) => color'
POST /cli -d "
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- CONFIG
CREATE TABLE products(title text, price float) regexp_filter = '(blue|red) => color'"$index = new \Manticoresearch\Index($client);
$index->setName('products');$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float']
],[
'regexp_filter' => '(blue|red) => color'
]);
##### Python:
utilsApi.sql('CREATE TABLE products(title text, price float) regexp_filter = \'(blue|red) => color\'')await utilsApi.sql('CREATE TABLE products(title text, price float) regexp_filter = \'(blue|red) => color\'')res = await utilsApi.sql('CREATE TABLE products(title text, price float) regexp_filter = \'(blue|red) => color\'');utilsApi.sql("CREATE TABLE products(title text, price float) regexp_filter = '(blue|red) => color'", true);utilsApi.Sql("CREATE TABLE products(title text, price float) regexp_filter = '(blue|red) => color'", true);utils_api.sql("CREATE TABLE products(title text, price float) regexp_filter = '(blue|red) => color'", Some(true)).await; # index '13"' as '13inch' regexp_filter = \b(\d+)\" => \1inch
# index 'blue' or 'red' as 'color'
regexp_filter = (blue|red) => color
type = rt
path = tbl
rt_field = title
rt_attr_uint = price
}
rt_attr_uint = price
}Поиск с подстановочными знаками — это распространённый тип текстового поиска. В 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*