Низкоуровневая токенизация

Когда текст индексируется в 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 можно узнать здесь.

Опции конфигурации индекса

charset_table

# 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'

Помимо определения символов и отображений, доступны несколько встроенных псевдонимов, которые можно использовать. Текущие псевдонимы:

  • chinese
  • cjk
  • cont
  • english
  • japanese
  • korean
  • non_cont (non_cjk)
  • russian
  • thai
‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • Java
  • C#
  • Rust
  • CONFIG
📋
CREATE TABLE products(title text, price float) charset_table = '0..9, english, _'

Если вы хотите поддерживать разные языки в поиске, определение наборов допустимых символов и правил свёртки для всех из них может быть трудоёмкой задачей. Мы упростили это для вас, предоставив таблицы символов по умолчанию — 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 "

Для отображения одного символа в несколько символов или наоборот может быть полезен regexp_filter.

blend_chars

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, @->_'"

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 = '+, &'"

min_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'"

Длины 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'"

ngram_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'"

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'"

Список игнорируемых символов. Необязательно, по умолчанию пустой.

Полезно в случаях, когда некоторые символы, такие как мягкий перенос (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'"

Режим индексации биграмм. Необязательно, по умолчанию отсутствует.

Индексация биграмм — это функция для ускорения поиска фраз. При индексации в индекс сохраняется список документов для всех или некоторых пар соседних слов. Этот список затем может использоваться во время поиска для значительного ускорения сопоставления фраз или подфраз.

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'"

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

Некоторые режимы индексации биграмм (см. %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'"

Тип словаря ключевых слов определяется одним из двух известных значений: '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'"

Лимит размера встроенных исключений, словоформ или стоп-слов. Необязательно, по умолчанию 16K.

При создании таблицы вышеуказанные файлы могут быть либо сохранены внешне вместе с таблицей, либо встроены непосредственно в таблицу. Файлы размером меньше `embedded_limit` сохраняются в таблице. Для больших файлов сохраняются только имена файлов. Это также упрощает перенос файлов таблицы на другой компьютер; зачастую достаточно просто скопировать один файл.

С меньшими файлами такое встраивание уменьшает количество внешних файлов, от которых зависит таблица, и облегчает обслуживание. Но в то же время нет смысла встраивать словарь wordforms размером 100 МБ в крошечную дельта-таблицу. Поэтому необходим порог по размеру, и embedded_limit — это тот самый порог.

table products {

embedded_limit = 32K

‹›
  • CONFIG
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'"

Список слов без позиций (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'"

Включает вычисление и сохранение длин полей (как для каждого документа, так и средних значений по индексу) в полнотекстовом индексе. Необязательно, по умолчанию 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_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=@#&'"

Инкремент позиции для слишком коротких (меньше 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'"

Список символов границ фраз. Опционально, по умолчанию пусто.

Этот список контролирует, какие символы будут рассматриваться как границы фраз, чтобы корректировать позиции слов и включить эмуляцию поиска на уровне фраз через поиск по близости. Синтаксис похож на %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'"

Инкремент позиции слова на границе фразы. Опционально, по умолчанию 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'"

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'"
Last modified: August 28, 2025