Типы данных

Полнотекстовые поля и атрибуты

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

Синтаксис имени поля

Имена полей в Manticore должны соответствовать следующим правилам:

  • Могут содержать буквы (a-z, A-Z), цифры (0-9) и дефисы (-)
  • Должны начинаться с буквы
  • Цифры могут появляться только после букв
  • Подчеркивание (_) — единственный разрешённый специальный символ
  • Имена полей не чувствительны к регистру

Например:

  • Допустимые имена полей: title, product_id, user_name_2
  • Недопустимые имена полей: 2title, -price, user@name

Полнотекстовые поля

Полнотекстовые поля:

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

Полнотекстовые поля представлены типом данных text. Все остальные типы данных называются «атрибутами».

Атрибуты

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

Часто требуется обрабатывать результаты полнотекстового поиска не только на основе совпадения ID документа и его ранга, но и на основе ряда других значений, связанных с документом. Например, может понадобиться отсортировать результаты поиска новостей по дате, а затем по релевантности, или искать товары в заданном ценовом диапазоне, или ограничить поиск по блогу постами, сделанными выбранными пользователями, или сгруппировать результаты по месяцу. Для эффективного выполнения таких задач Manticore позволяет добавлять к каждому документу не только полнотекстовые поля, но и дополнительные атрибуты. Эти атрибуты можно использовать для фильтрации, сортировки или группировки полнотекстовых совпадений, а также для поиска только по атрибутам.

Атрибуты, в отличие от полнотекстовых полей, не индексируются полнотекстово. Они хранятся в таблице, но по ним нельзя выполнять полнотекстовый поиск.

Хорошим примером атрибутов может служить таблица сообщений форума. Предположим, что полнотекстовым поиском должны быть доступны только поля title и content — но иногда требуется ограничить поиск определённым автором или подфорумом (то есть искать только те строки, у которых есть конкретные значения author_id или forum_id); или сортировать совпадения по столбцу post_date; или группировать совпадающие сообщения по месяцу из post_date и подсчитывать количество совпадений в каждой группе.

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • Javascript
  • Java
  • C#
  • Rust
  • config
📋
CREATE TABLE forum(title text, content text, author_id int, forum_id int, post_date timestamp);

В этом примере показан запуск полнотекстового запроса с фильтрацией по author_id, forum_id и сортировкой по post_date.

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • java
  • C#
  • Rust
📋
select * from forum where author_id=123 and forum_id in (1,3,7) order by post_date desc

Строковое и колонковое хранение атрибутов

Manticore поддерживает два типа хранения атрибутов:

  • строковое — традиционное хранение, доступное в Manticore Search из коробки
  • колонковое — предоставляется Manticore Columnar Library

Как можно понять из названий, они хранят данные по-разному. Традиционное строковое хранение:

  • хранит атрибуты без сжатия
  • все атрибуты одного документа хранятся в одной строке рядом друг с другом
  • строки хранятся одна за другой
  • доступ к атрибутам осуществляется просто умножением ID строки на шаг (длину одного вектора) и получением нужного атрибута из рассчитанного адреса в памяти. Это обеспечивает очень низкую задержку случайного доступа.
  • атрибуты должны находиться в памяти для достижения приемлемой производительности, иначе из-за строковой природы хранения Manticore может читать с диска слишком много ненужных данных, что во многих случаях не оптимально.

В случае колонкового хранения:

  • каждый атрибут хранится независимо от всех остальных в отдельной «колонке»
  • хранилище разбито на блоки по 65536 записей
  • блоки хранятся в сжатом виде. Это часто позволяет хранить всего несколько различных значений вместо хранения всех значений, как в строковом хранении. Высокое сжатие позволяет быстрее читать с диска и значительно снижает требования к памяти
  • при индексировании данных схема хранения выбирается для каждого блока отдельно. Например, если все значения в блоке одинаковы, он получает «const» хранение, и для всего блока хранится только одно значение. Если в блоке менее 256 уникальных значений, он получает «table» хранение и хранит индексы в таблицу значений вместо самих значений
  • поиск в блоке может быть досрочно отклонён, если ясно, что запрашиваемое значение отсутствует в блоке.

Колонковое хранение было разработано для обработки больших объёмов данных, которые не помещаются в ОЗУ, поэтому рекомендации таковы:

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

Как переключаться между хранилищами

Традиционное построчное хранение является значением по умолчанию, поэтому если вы хотите, чтобы всё хранилось построчно, вам не нужно ничего делать при создании таблицы.

Чтобы включить колонковое хранение, нужно:

  • указать engine='columnar' в CREATE TABLE, чтобы все атрибуты таблицы были колонковыми. Если вы хотите, чтобы конкретный атрибут оставался построчным, нужно добавить engine='rowwise' при его объявлении. Например:
    create table tbl(title text, type int, price float engine='rowwise') engine='columnar'
  • указать engine='columnar' для конкретного атрибута в CREATE TABLE, чтобы сделать его колонковым. Например:
    create table tbl(title text, type int, price float engine='columnar');

    или

    create table tbl(title text, type int, price float engine='columnar') engine='rowwise';
  • в plain режиме нужно перечислить атрибуты, которые вы хотите сделать колонковыми, в columnar_attrs.

Ниже приведён список типов данных, поддерживаемых Manticore Search:

Идентификатор документа

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

При создании таблицы вы можете явно указать ID, но независимо от используемого типа данных он всегда будет вести себя, как описано выше — храниться как беззнаковое 64-битное число, но отображаться как знаковое 64-битное целое.

mysql> CREATE TABLE tbl(id bigint, content text);
DESC tbl;
+---------+--------+----------------+
| Field   | Type   | Properties     |
+---------+--------+----------------+
| id      | bigint |                |
| content | text   | indexed stored |
+---------+--------+----------------+
2 rows in set (0.00 sec)

Вы также можете вообще не указывать ID, он будет включён автоматически.

mysql> CREATE TABLE tbl(content text);
DESC tbl;
+---------+--------+----------------+
| Field   | Type   | Properties     |
+---------+--------+----------------+
| id      | bigint |                |
| content | text   | indexed stored |
+---------+--------+----------------+
2 rows in set (0.00 sec)

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

Интерфейс MySQL/SQL:

  • Идентификаторы больше 2^63-1 будут отображаться как отрицательные числа.
  • При фильтрации по таким большим ID нужно использовать их знаковое представление.
  • Используйте функцию UINT64(), чтобы увидеть фактическое беззнаковое значение.

Интерфейс JSON/HTTP:

  • ID всегда отображаются как их исходные беззнаковые значения, независимо от размера.
  • Для фильтрации можно использовать как знаковое, так и беззнаковое представление.
  • Операции вставки принимают полный диапазон беззнаковых 64-битных чисел.

Например, создадим таблицу и вставим несколько значений около 2^63:

mysql> create table t(id_text string);
Query OK, 0 rows affected (0.01 sec)
mysql> insert into t values(9223372036854775807, '2 ^ 63 - 1'),(9223372036854775808, '2 ^ 63');
Query OK, 2 rows affected (0.00 sec)

Некоторые ID в результатах отображаются как отрицательные числа, потому что они превышают 2^63-1. Однако использование UINT64(id) позволяет увидеть их фактические беззнаковые значения:

mysql> select *, uint64(id) from t;
+----------------------+------------+---------------------+
| id                   | id_text    | uint64(id)          |
+----------------------+------------+---------------------+
|  9223372036854775807 | 2 ^ 63 - 1 | 9223372036854775807 |
| -9223372036854775808 | 2 ^ 63     | 9223372036854775808 |
+----------------------+------------+---------------------+
2 rows in set (0.00 sec)
--- 2 out of 2 results in 0ms ---

Для запросов документов с ID меньше 2^63 можно использовать беззнаковое значение напрямую:

mysql> select * from t where id = 9223372036854775807;
+---------------------+------------+
| id                  | id_text    |
+---------------------+------------+
| 9223372036854775807 | 2 ^ 63 - 1 |
+---------------------+------------+
1 row in set (0.00 sec)
--- 1 out of 1 results in 0ms ---

Однако для ID, начиная с 2^63, нужно использовать знаковое значение:

mysql> select * from t where id = -9223372036854775808;
+----------------------+---------+
| id                   | id_text |
+----------------------+---------+
| -9223372036854775808 | 2 ^ 63  |
+----------------------+---------+
1 row in set (0.00 sec)
--- 1 out of 1 results in 0ms ---

Если использовать беззнаковое значение вместо этого, будет ошибка:

mysql> select * from t where id = 9223372036854775808;
ERROR 1064 (42000): number 9223372036854775808 is out of range [-9223372036854775808..9223372036854775807]

Значения, не помещающиеся в 64 бита, вызовут аналогичную ошибку:

mysql> select * from t where id = -9223372036854775809;
ERROR 1064 (42000): number -9223372036854775809 is out of range [-9223372036854775808..9223372036854775807]

Различия интерфейсов при больших ID

Различия в поведении между интерфейсами MySQL/SQL и JSON/HTTP становятся более заметными при очень больших идентификаторах документов. Вот полный пример:

Интерфейс MySQL/SQL:

mysql> drop table if exists t; create table t; insert into t values(17581446260360033510);
Query OK, 0 rows affected (0.01 sec)
mysql> select * from t;
+---------------------+
| id                  |
+---------------------+
| -865297813349518106 |
+---------------------+
mysql> select *, uint64(id) from t;
+---------------------+----------------------+
| id                  | uint64(id)           |
+---------------------+----------------------+
| -865297813349518106 | 17581446260360033510 |
+---------------------+----------------------+
mysql> select * from t where id = -865297813349518106;
+---------------------+
| id                  |
+---------------------+
| -865297813349518106 |
+---------------------+
mysql> select * from t where id = 17581446260360033510;
ERROR 1064 (42000): number 17581446260360033510 is out of range [-9223372036854775808..9223372036854775807]

Интерфейс JSON/HTTP:

# Search returns the original unsigned value
curl -s 0:9308/search -d '{"table": "t"}'
{
  "took": 0,
  "timed_out": false,
  "hits": {
    "total": 1,
    "total_relation": "eq",
    "hits": [
      {
        "_id": 17581446260360033510,
        "_score": 1,
        "_source": {}
      }
    ]
  }
}
# Both signed and unsigned values work for filtering
curl -s 0:9308/search -d '{"table": "t", "query": {"equals": {"id": 17581446260360033510}}}'
curl -s 0:9308/search -d '{"table": "t", "query": {"equals": {"id": -865297813349518106}}}'
# Insert with maximum unsigned 64-bit value
curl -s 0:9308/insert -d '{"table": "t", "id": 18446744073709551615, "doc": {}}'

Это означает, что при работе с большими идентификаторами документов:

  1. Интерфейс MySQL требует использования знакового представления для запросов, но может отображать беззнаковое значение с помощью UINT64()
  2. Интерфейс JSON последовательно использует беззнаковые значения для отображения и принимает оба представления для фильтрации

Типы данных символов

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

string|text [stored|attribute] [indexed]

Свойства:

  1. indexed — полнотекстовый индекс (можно использовать в полнотекстовых запросах)
  2. stored — хранится в docstore (хранится на диске, не в ОЗУ, ленивое чтение)
  3. attribute — делает его строковым атрибутом (можно сортировать/группировать по нему)

Указание хотя бы одного свойства отменяет все свойства по умолчанию (см. ниже), то есть если вы решите использовать пользовательскую комбинацию свойств, нужно перечислить все свойства, которые хотите.

Если свойства не указаны:

string и text — это синонимы, но если не указать свойства, они по умолчанию означают разное:

  • просто string по умолчанию означает attribute (подробности ниже).
  • просто text по умолчанию означает stored + indexed (подробности ниже).

Текст

Тип данных текст (просто text или text/string indexed) формирует полнотекстовую часть таблицы. Текстовые поля индексируются и по ним можно искать ключевые слова.

Текст проходит через конвейер анализатора, который разбивает текст на слова, применяет морфологические преобразования и т. д. В итоге из этого текста строится полнотекстовая таблица (специальная структура данных, позволяющая быстро искать ключевое слово).

Полнотекстовые поля можно использовать только в условии MATCH() и нельзя использовать для сортировки или агрегации. Слова хранятся в обратном индексе вместе с ссылками на поля, которым они принадлежат, и позициями в поле. Это позволяет искать слово внутри каждого поля и использовать расширенные операторы, например, близость. По умолчанию исходный текст полей индексируется и хранится в хранилище документов. Это значит, что исходный текст можно вернуть в результатах запроса и использовать в подсветке результатов поиска.

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • java
  • C#
  • Rust
  • config
📋
CREATE TABLE products(title text);

Это поведение можно переопределить, явно указав, что текст индексируется только.

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • java
  • C#
  • Rust
  • config
📋
CREATE TABLE products(title text indexed);

Поля имеют имена, и вы можете ограничить поиск одним полем (например, искать только по "title") или подмножеством полей (например, только "title" и "abstract"). Вы можете иметь до 256 полнотекстовых полей.

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • java
  • C#
  • Rust
📋
select * from products where match('@title first');

Строка

В отличие от полнотекстовых полей, строковые атрибуты (просто string или string/text attribute) хранятся в том виде, в каком они получены, и не могут использоваться в полнотекстовом поиске. Вместо этого они возвращаются в результатах, могут использоваться в условии WHERE для фильтрации по сравнению или REGEX, а также для сортировки и агрегации. В общем, не рекомендуется хранить большие тексты в строковых атрибутах, лучше использовать строковые атрибуты для метаданных, таких как имена, заголовки, теги, ключи.

Если вы хотите также индексировать строковый атрибут, вы можете указать его как string attribute indexed. Это позволит полнотекстовый поиск и будет работать как атрибут.

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • java
  • C#
  • Rust
  • config
📋
CREATE TABLE products(title text, keys string);
MORE

Хранение бинарных данных в Manticore

В Manticore нет специального типа поля для бинарных данных, но вы можете безопасно хранить их, используя кодирование base64 и типы полей text stored или string stored (которые являются синонимами). Если не кодировать бинарные данные, их части могут потеряться — например, Manticore обрезает конец строки, если встречает нулевой байт.

Вот пример, где мы кодируем команду ls с помощью base64, сохраняем её в Manticore, а затем декодируем, чтобы проверить, что контрольная сумма MD5 осталась неизменной:

‹›
  • Example
Example
📋
# md5sum /bin/ls
43d1b8a7ccda411118e2caba685f4329  /bin/ls
# encoded_data=`base64 -i /bin/ls `
# mysql -P9306 -h0 -e "drop table if exists test; create table test(data text stored); insert into test(data) values('$encoded_data')"
# mysql -P9306 -h0 -NB -e "select data from test" | base64 -d > /tmp/ls | md5sum
43d1b8a7ccda411118e2caba685f4329  -

Целое число

Тип integer позволяет хранить 32-битные беззнаковые целочисленные значения.

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • java
  • C#
  • Rust
  • config
📋
CREATE TABLE products(title text, price int);

Целые числа могут храниться в меньших размерах, чем 32-битные, путем указания количества бит. Например, если мы хотим сохранить числовое значение, которое, как мы знаем, не будет больше 8, тип можно определить как bit(3). Целые числа с битовой длиной работают медленнее, чем полноразмерные, но требуют меньше оперативной памяти. Они сохраняются в 32-битных блоках, поэтому для экономии места их следует группировать в конце определения атрибутов (иначе целое число с битовой длиной между двумя полноразмерными целыми также займет 32 бита).

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • java
  • C#
  • Rust
  • config
📋
CREATE TABLE products(title text, flags bit(3), tags bit(2) );

Большое целое число

Большие целые числа (bigint) — это 64-битные знаковые целые числа.

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • java
  • C#
  • Rust
  • config
📋
CREATE TABLE products(title text, price bigint );

Булевый тип

Объявляет булевый атрибут. Это эквивалентно целочисленному атрибуту с битовой длиной 1.

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • java
  • C#
  • Rust
  • config
📋
CREATE TABLE products(title text, sold bool );

Метки времени

Тип timestamp представляет собой Unix-метки времени, которые хранятся как 32-битные целые числа. В отличие от базовых целых чисел, тип timestamp позволяет использовать функции времени и даты. Преобразование из строковых значений происходит по следующим правилам:

  • Числа без разделителей, длиной не менее 10 символов, преобразуются в метки времени как есть.
  • %Y-%m-%dT%H:%M:%E*S%Z
  • %Y-%m-%d'T'%H:%M:%S%Z
  • %Y-%m-%dT%H:%M:%E*S
  • %Y-%m-%dT%H:%M:%s
  • %Y-%m-%dT%H:%M
  • %Y-%m-%dT%H
  • %Y-%m-%d
  • %Y-%m
  • %Y

Значения этих спецификаторов преобразования подробно описаны в руководстве strptime, за исключением %E*S, который обозначает миллисекунды.

Обратите внимание, что автоматическое преобразование меток времени не поддерживается в простых таблицах.

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • java
  • C#
  • Rust
  • config
📋
CREATE TABLE products(title text, date timestamp);

Число с плавающей точкой

Вещественные числа хранятся как 32-битные числа с плавающей точкой одинарной точности по стандарту IEEE 754.

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • java
  • C#
  • Rust
  • config
📋
CREATE TABLE products(title text, coeff float);

В отличие от целочисленных типов, сравнивать два числа с плавающей точкой на равенство не рекомендуется из-за возможных ошибок округления. Более надежный подход — использовать сравнение с допуском, проверяя абсолютную погрешность.

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • java
  • C#
  • Rust
📋
select abs(a-b)<=0.00001 from products

Еще одна альтернатива, которая также может использоваться для выполнения IN(attr,val1,val2,val3) — сравнивать числа с плавающей точкой как целые, выбирая множитель и преобразуя числа с плавающей точкой в целые в операциях. Следующий пример иллюстрирует изменение IN(attr,2.0,2.5,3.5) для работы с целочисленными значениями.

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • java
  • C#
  • Rust
📋
select in(ceil(attr*100),200,250,350) from products

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

Теперь Manticore сначала выводит число с 6 знаками, затем парсит и сравнивает его с исходным значением. Если они не совпадают, добавляются дополнительные знаки, пока не совпадут.

Например, если значение с плавающей точкой было вставлено как 19.45, Manticore отобразит его как 19.450001, чтобы точно представить сохраненное значение.

‹›
  • Example
Example
📋
insert into t(id, f) values(1, 19.45)
--------------
Query OK, 1 row affected (0.02 sec)
--------------
select * from t
--------------
+------+-----------+
| id   | f         |
+------+-----------+
|    1 | 19.450001 |
+------+-----------+
1 row in set (0.00 sec)
--- 1 out of 1 results in 0ms ---

JSON

Этот тип данных позволяет хранить JSON-объекты, что особенно полезно для работы с данными без схемы. При определении JSON-значений убедитесь, что включены открывающие и закрывающие фигурные скобки { и } для объектов или квадратные скобки [ и ] для массивов. Хотя JSON не поддерживается колонковым хранением, он может храниться в традиционном построчном хранении. Стоит отметить, что оба типа хранения могут комбинироваться в одной таблице.

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • java
  • C#
  • Rust
  • config
📋
CREATE TABLE products(title text, data json);

Свойства JSON могут использоваться в большинстве операций. Также существуют специальные функции, такие как ALL(), ANY(), GREATEST(), LEAST() и INDEXOF(), которые позволяют обходить массивы свойств.

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • java
  • C#
  • Rust
📋
select indexof(x>2 for x in data.intarray) from products

Текстовые свойства обрабатываются так же, как строки, поэтому их нельзя использовать в выражениях полнотекстового поиска. Однако можно использовать строковые функции, такие как REGEX().

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • java
  • C#
  • Rust
📋
select regex(data.name, 'est') as c from products where c>0

В случае свойств JSON может потребоваться принудительное указание типа данных для правильной работы в некоторых ситуациях. Например, при работе с числами с плавающей точкой необходимо использовать DOUBLE() для правильной сортировки.

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • java
  • C#
  • Rust
📋
select * from products order by double(data.myfloat) desc

Float vector

Атрибуты векторных чисел с плавающей запятой позволяют хранить списки переменной длины из чисел с плавающей запятой, преимущественно используемые для приложений машинного обучения и поиска по сходству. Этот тип отличается от мультизначных атрибутов (MVA) по нескольким важным аспектам:

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

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

Использование и ограничения

  • В настоящее время поддерживаются только в таблицах реального времени
  • Могут использоваться только в поисках KNN (k-ближайших соседей)
  • Не поддерживаются в обычных таблицах или других функциях/выражениях
  • При использовании с настройками KNN нельзя UPDATE значения float_vector. Используйте REPLACE
  • При использовании без настроек KNN можно UPDATE значения float_vector
  • Векторы с плавающей запятой нельзя использовать в обычных фильтрах или сортировке
  • Единственный способ фильтровать по значениям float_vector — через операции векторного поиска (KNN)

Распространённые случаи использования

  • Текстовые эмбеддинги для семантического поиска
  • Векторы рекомендательных систем
  • Эмбеддинги изображений для поиска по сходству
  • Векторы признаков для машинного обучения

Имейте в виду, что тип данных float_vector несовместим с механизмом Auto schema.

Для получения подробной информации о настройке векторов с плавающей запятой и их использовании в поисках смотрите KNN search.

Автоматические эмбеддинги (рекомендуется)

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

Преимущества автоматических эмбеддингов

  • Упрощённый рабочий процесс: Просто вставляйте текст, эмбеддинги генерируются автоматически
  • Нет необходимости вручную вычислять векторы: Не нужно запускать отдельные модели эмбеддингов
  • Последовательные эмбеддинги: Одна и та же модель обеспечивает согласованное представление векторов
  • Поддержка нескольких моделей: Выбор из моделей sentence-transformers, OpenAI, Voyage и Jina
  • Гибкий выбор полей: Контроль над тем, какие поля используются для генерации эмбеддингов

Создание таблиц с автоматическими эмбеддингами

При создании таблицы с автоматическими эмбеддингами укажите следующие дополнительные параметры:

  • MODEL_NAME: модель эмбеддингов для автоматической генерации векторов
  • FROM: какие поля использовать для генерации эмбеддингов (пустая строка означает все текстовые/строковые поля)

Поддерживаемые модели эмбеддингов:

  • Sentence Transformers: Любая подходящая модель BERT на Hugging Face (например, sentence-transformers/all-MiniLM-L6-v2) — API ключ не требуется. Manticore загружает модель при создании таблицы.
  • OpenAI: Модели эмбеддингов OpenAI, например openai/text-embedding-ada-002 — требует параметр API_KEY='<OPENAI_API_KEY>'
  • Voyage: Модели эмбеддингов Voyage AI — требует параметр API_KEY='<VOYAGE_API_KEY>'
  • Jina: Модели эмбеддингов Jina AI — требует параметр API_KEY='<JINA_API_KEY>'
‹›
  • SQL
SQL
📋

Использование модели sentence-transformers (API ключ не требуется)

CREATE TABLE products (
    title TEXT,
    description TEXT,
    embedding_vector FLOAT_VECTOR KNN_TYPE='hnsw' HNSW_SIMILARITY='l2'
    MODEL_NAME='sentence-transformers/all-MiniLM-L6-v2' FROM='title'
);

Использование модели OpenAI (требуется параметр API_KEY)

CREATE TABLE products_openai (
    title TEXT,
    content TEXT,
    embedding_vector FLOAT_VECTOR KNN_TYPE='hnsw' HNSW_SIMILARITY='cosine'
    MODEL_NAME='openai/text-embedding-ada-002' FROM='title,content' API_KEY='<OPENAI_API_KEY>'
);

Использование всех текстовых полей для эмбеддингов (FROM пустой)

CREATE TABLE products_all_fields (
    title TEXT,
    description TEXT,
    tags TEXT,
    embedding_vector FLOAT_VECTOR KNN_TYPE='hnsw' HNSW_SIMILARITY='l2'
    MODEL_NAME='sentence-transformers/all-MiniLM-L6-v2' FROM=''
);

Использование параметра FROM

Параметр FROM контролирует, какие поля используются для генерации эмбеддингов:

  • Конкретные поля: FROM='title' — используется только поле title
  • Несколько полей: FROM='title,description' — объединяются и используются поля title и description
  • Все текстовые поля: FROM='' (пусто) — используются все поля типа text (полнотекстовые поля) и string (строковые атрибуты) в таблице
  • Пустые векторы: Можно вставлять пустые векторы с помощью (), чтобы исключить документы из векторного поиска

Вставка данных с автоматическими эмбеддингами

При использовании автоматических эмбеддингов не указывайте поле вектора в ваших операторах INSERT. Эмбеддинги автоматически генерируются из указанных текстовых полей:

-- Insert text data - embeddings generated automatically
INSERT INTO products (title, description) VALUES 
('smartphone', 'latest mobile device with camera'),
('laptop computer', 'portable workstation for developers');
-- Insert with empty vector (excluded from vector search)
INSERT INTO products (title, description, embedding_vector) VALUES
('no-vector item', 'this item has no embedding', ());

Ручное использование векторов с плавающей запятой

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

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • java
  • C#
  • Rust
  • config
📋
CREATE TABLE products(title text, image_vector float_vector);

Мультизначное целое число (MVA)

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

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • java
  • C#
  • Rust
  • config
📋
CREATE TABLE products(title text, product_codes multi);

It supports filtering and aggregation, but not sorting. Filtering can be done using a condition that requires at least one element to pass (using ANY()) or all elements (ALL()) to pass.

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • java
  • C#
  • Rust
📋
select * from products where any(product_codes)=3

Information like least or greatest element and length of the list can be extracted. An example shows ordering by the least element of a multi-value attribute.

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • java
  • C#
  • Rust
📋
select least(product_codes) l from products order by l asc

When grouping by a multi-value attribute, a document will contribute to as many groups as there are different values associated with that document. For instance, if a collection contains exactly one document having a 'product_codes' multi-value attribute with values 5, 7, and 11, grouping on 'product_codes' will produce 3 groups with COUNT(*)equal to 1 and GROUPBY() key values of 5, 7, and 11, respectively. Also, note that grouping by multi-value attributes may lead to duplicate documents in the result set because each document can participate in many groups.

‹›
  • SQL
SQL
📋
insert into products values ( 1, 'doc one', (5,7,11) );
select id, count(*), groupby() from products group by product_codes;
‹›
Response
Query OK, 1 row affected (0.00 sec)
+------+----------+-----------+
| id   | count(*) | groupby() |
+------+----------+-----------+
|    1 |        1 |        11 |
|    1 |        1 |         7 |
|    1 |        1 |         5 |
+------+----------+-----------+
3 rows in set (0.00 sec)

The order of the numbers inserted as values of multivalued attributes is not preserved. Values are stored internally as a sorted set.

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • java
  • C#
  • Rust
📋
insert into product values (1,'first',(4,2,1,3));
select * from products;
‹›
Response
Query OK, 1 row affected (0.00 sec)
+------+---------------+-------+
| id   | product_codes | title |
+------+---------------+-------+
|    1 | 1,2,3,4       | first |
+------+---------------+-------+
1 row in set (0.01 sec)

Multi-value big integer

A data type that allows storing variable-length lists of 64-bit signed integers. It has the same functionality as multi-value integer.

‹›
  • SQL
  • JSON
  • PHP
  • Python
  • Python-asyncio
  • javascript
  • java
  • C#
  • Rust
  • config
📋
CREATE TABLE products(title text, values multi64);

Columnar attribute properties

When you use the columnar storage you can specify the following properties for the attributes.

fast_fetch

By default, Manticore Columnar storage stores all attributes in a columnar fashion, as well as in a special docstore row by row. This enables fast execution of queries like SELECT * FROM ..., especially when fetching a large number of records at once. However, if you are sure that you do not need it or wish to save disk space, you can disable it by specifying fast_fetch='0' when creating a table or (if you are defining a table in a config) by using columnar_no_fast_fetch as shown in the following example.

‹›
  • RT mode
  • Plain mode
📋
create table t(a int, b int fast_fetch='0') engine='columnar'; desc t;
‹›
Response
+-------+--------+---------------------+
| Field | Type   | Properties          |
+-------+--------+---------------------+
| id    | bigint | columnar fast_fetch |
| a     | uint   | columnar fast_fetch |
| b     | uint   | columnar            |
+-------+--------+---------------------+
3 rows in set (0.00 sec)
Last modified: September 08, 2025