数据类型

全文字段与属性

Manticore 的数据类型可以分为两类:全文字段和属性。

字段名语法

Manticore 中的字段名必须遵循以下规则:

  • 可以包含字母(a-z, A-Z)、数字(0-9)和连字符(-)
  • 必须以字母开头
  • 数字只能出现在字母之后
  • 下划线(_)是唯一允许的特殊字符
  • 字段名不区分大小写

例如:

  • 有效的字段名:titleproduct_iduser_name_2
  • 无效的字段名:2title-priceuser@name

全文字段

全文字段:

  • 可以使用自然语言处理算法进行索引,因此可以搜索关键词
  • 不能用于排序或分组
  • 可以检索原始文档内容
  • 原始文档内容可用于高亮显示

全文字段由数据类型 text 表示。所有其他数据类型都称为“属性”。

属性

属性是与每个文档关联的非全文值,可用于在搜索期间执行非全文过滤、排序和分组。

通常,不仅需要根据匹配的文档 ID 及其排名来处理全文搜索结果,还需要基于许多其他每文档值进行处理。例如,可能需要按日期和相关性对新闻搜索结果进行排序,或在指定价格范围内搜索产品,或将博客搜索限制在选定用户发布的帖子中,或按月份对结果进行分组。为了实现这一点,Manticore 不仅支持全文字段,还允许为每个文档添加额外的属性。这些属性可用于过滤、排序或分组全文匹配项,或仅按属性进行搜索。

与全文字段不同,属性不进行全文索引。它们存储在表中,但无法像全文那样进行搜索。

属性的一个很好的例子是论坛帖子表。假设只有标题和内容字段需要进行全文搜索——但有时还需要将搜索限制在特定作者或子论坛(即,仅搜索那些具有特定 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_idforum_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 列式库 提供

从它们的名称可以理解,它们以不同的方式存储数据。传统的 行式存储

  • 以未压缩的方式存储属性
  • 同一文档的所有属性存储在彼此靠近的一行中
  • 行按顺序存储
  • 访问属性基本上是通过将行 ID 乘以步幅(单个向量的长度)并从计算出的内存位置获取请求的属性来实现。这提供了非常低的随机访问延迟。
  • 属性必须位于内存中才能获得可接受的性能,否则由于存储的行式特性,Manticore 可能不得不从磁盘读取太多不需要的数据,这在许多情况下是次优的。

使用 列式存储

  • 每个属性都独立于所有其他属性存储在其单独的“列”中
  • 存储被分成 65536 个条目的块
  • 块以压缩形式存储。这通常允许仅存储几个不同的值,而不是像行式存储那样存储所有值。高压缩比允许更快地从磁盘读取,并大大降低内存需求
  • 当数据被索引时,每个块独立选择存储方案。例如,如果一个块中的所有值都相同,则采用“常量”存储,整个块只存储一个值。如果每个块的唯一值少于 256 个,则采用“表”存储,存储值表的索引而不是值本身
  • 如果明确请求的值不在块中,可以提前拒绝在块中的搜索。

列式存储旨在处理无法放入 RAM 的大数据量,因此建议如下:

  • 如果您有足够的内存容纳所有属性,您将从行式存储中受益
  • 否则,列式存储仍然可以为您提供不错的性能,同时内存占用低得多,这将允许您在表中存储更多的文档

如何在存储类型之间切换

传统的行式存储是默认方式,因此如果您希望所有内容都以行式存储,创建表时无需进行任何操作。

要启用列式存储,您需要:

  • CREATE TABLE 中指定 engine='columnar',使表的所有属性变为列式。然后,如果您希望保留特定属性为行式,需要在声明该属性时添加 engine='rowwise'。例如:
    create table tbl(title text, type int, price float engine='rowwise') engine='columnar'
  • CREATE TABLE 中为特定属性指定 engine='columnar',使其变为列式。例如:
    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 支持的数据类型列表:

文档 ID

文档标识符是一个必需的属性,必须是唯一的 64 位无符号整数。创建表时可以显式指定文档 ID,但即使未指定,文档 ID 也始终会被启用。文档 ID 无法更新。

创建表时,您可以显式指定 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)

处理文档 ID 时,重要的是要知道它们在内部以无符号 64 位整数存储,但根据接口的不同,处理方式也有所不同:

MySQL/SQL 接口:

  • 大于 2^63-1 的 ID 将显示为负数。
  • 过滤此类大 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 ---

但是,对于从 2^63 开始的 ID,需要使用有符号值:

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 接口之间的行为差异在处理非常大的文档 ID 时变得更加明显。以下是一个全面的示例:

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": {}}'

这意味着在处理大文档 ID 时:

  1. MySQL 接口 要求查询时使用有符号表示,但可以通过 UINT64() 显示无符号值
  2. JSON 接口 始终使用无符号值显示,并接受两种表示进行过滤

字符数据类型

通用语法:

string|text [stored|attribute] [indexed]

属性:

  1. indexed - 全文索引(可用于全文查询)
  2. stored - 存储在文档存储中(存储在磁盘上,而非 RAM 中,惰性读取)
  3. attribute - 使其成为字符串属性(可以按其排序/分组)

指定至少一个属性会覆盖所有默认属性(见下文),即,如果您决定使用自定义属性组合,需要列出所有您想要的属性。

未指定任何属性:

stringtext 是别名,但如果您不指定任何属性,它们默认表示不同的含义:

  • string 默认表示 attribute(详见 下文)。
  • text 默认表示 stored + indexed(详见 下文)。

文本

文本(仅 texttext/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');

字符串

与全文字段不同,字符串属性(仅stringstring/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 storedstring stored字段类型(它们是同义词)来安全地存储它。如果您不对二进制数据进行编码,部分数据可能会丢失——例如,如果遇到空字节,Manticore会修剪字符串的末尾。

这是一个示例,我们使用base64编码ls命令,将其存储在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  -

整数

整数类型允许存储32位无符号整数值。

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

整数可以通过指定位数以比32位更短的尺寸存储。例如,如果我们想存储一个我们知道不会大于8的数值,类型可以定义为bit(3)。位计数整数比全尺寸整数性能更慢,但它们需要更少的RAM。它们以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 );

时间戳

时间戳类型表示Unix时间戳,以32位整数存储。与基本整数不同,时间戳类型允许使用时间和日期函数。从字符串值转换遵循以下规则:

  • 不带分隔符的数字,且长度至少为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

在处理浮点值的情况下,可能需要强制执行数据类型以确保某些情况下的正确功能。例如,当处理浮点值时,必须使用DOUBLE()以确保正确的排序。

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

Float vector

浮点向量属性允许存储可变长度的浮点数列表,主要用于机器学习应用和相似性搜索。此类型与多值整数(MVA)(MVAs)在几个重要方面不同:

  • 保留值的确切顺序(与MVAs不同,MVAs可能会重新排序)
  • 保留重复值(与MVAs不同,MVAs会去重)
  • 插入时无需额外处理(与MVAs不同,MVAs会排序和去重)

重要: float_vector 数据类型与 自动模式 机制不兼容。

一般限制

  • 目前仅支持实时表(不支持普通表)
  • 其他函数或表达式中不支持
  • 不能在常规过滤器或排序中使用

使用浮点向量与 KNN(向量搜索)

当你配置 float_vector 属性并设置 KNN 参数时,你将启用向量相似性搜索功能。这允许你执行 k-最近邻搜索,根据向量距离查找相似文档。

功能

你可以做到:

  • 执行 KNN(k-最近邻)向量搜索以查找相似文档
  • 构建语义搜索、推荐和 AI 驱动的功能
  • 使用自动嵌入从文本中自动生成向量

你不能做到:

  • UPDATE float_vector 值(必须使用 REPLACE 代替)
  • 在常规过滤器或排序中使用浮点向量
  • 除了通过向量搜索操作,不能通过 float_vector 值进行过滤

参数

当你创建带有 float_vector 属性的表以进行 KNN 搜索时,可以指定以下参数:

必填参数:

  • KNN_TYPE:目前仅支持 'hnsw'
  • KNN_DIMS:向量的维度数(手动插入向量时必需,使用 MODEL_NAME 时可省略)
  • HNSW_SIMILARITY:距离函数 - 'l2''ip'(内积)或 'cosine'

可选参数:

  • HNSW_M:图中的最大连接数(默认:16)
  • HNSW_EF_CONSTRUCTION:构建时间/准确性权衡(默认:200)

自动嵌入参数(当使用 MODEL_NAME 时):

  • MODEL_NAME:使用的嵌入模型(例如,'sentence-transformers/all-MiniLM-L6-v2''openai/text-embedding-ada-002'
  • FROM:用于生成嵌入的字段名列表(逗号分隔),或空字符串 '' 表示使用所有文本/字符串字段
  • API_KEY:基于 API 的模型(OpenAI、Voyage、Jina)的 API 密钥

有关设置浮点向量并在搜索中使用它们的详细信息,请参阅KNN搜索

方法 1:自动嵌入(推荐)

处理浮点向量最简便的方式是使用自动嵌入。此功能使用机器学习模型自动从您的文本数据生成嵌入,从而消除手动计算和插入向量的需要。

自动嵌入的优势

  • 简化的工作流程:只需插入文本,嵌入会自动生成
  • 无需手动计算向量:无需运行单独的嵌入模型
  • 一致的嵌入:相同的模型确保一致的向量表示
  • 多模型支持:可选择 sentence-transformersQwen 嵌入模型、OpenAI、Voyage 和 Jina 模型
  • 灵活的字段选择:控制用于生成嵌入的字段

创建带有自动嵌入的表

在创建带有自动嵌入的表时,指定以下附加参数:

  • MODEL_NAME:用于自动向量生成的嵌入模型
  • FROM:用于生成嵌入的字段(空字符串表示所有文本/字符串字段)

支持的嵌入模型:

  • Sentence Transformers:任何 适合的 BERT 基础 Hugging Face 模型(例如,sentence-transformers/all-MiniLM-L6-v2)——无需 API 密钥。Manticore 在创建表时下载模型。
  • Qwen 本地嵌入:Qwen 嵌入模型,如 Qwen/Qwen3-Embedding-0.6B——不需要 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'
);

使用 Qwen 本地嵌入(不需要 API 密钥)

CREATE TABLE products_qwen (
    title TEXT,
    description TEXT,
    embedding_vector FLOAT_VECTOR KNN_TYPE='hnsw' HNSW_SIMILARITY='l2'
    MODEL_NAME='Qwen/Qwen3-Embedding-0.6B' 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' - 仅使用标题字段
  • 多个字段FROM='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', ());

方法 2:手动向量插入

或者,你可以手动插入预计算的向量数据。这需要你使用外部工具或模型自行计算向量,然后将其插入到 Manticore 中。

重要提示: 当使用 HNSW_SIMILARITY='cosine' 时,插入时向量会自动归一化为单位向量(数学长度/幅度为 1.0 的向量)。这种归一化保留了向量的方向,同时标准化了其长度,这是高效余弦相似性计算所必需的。这意味着存储的值将与你的原始输入值不同。

‹›
  • SQL
SQL
📋
CREATE TABLE products (
    title TEXT,
    image_vector FLOAT_VECTOR KNN_TYPE='hnsw' KNN_DIMS='4' HNSW_SIMILARITY='l2'
);
INSERT INTO products VALUES 
(1, 'yellow bag', (0.653448,0.192478,0.017971,0.339821)),
(2, 'white bag', (-0.148894,0.748278,0.091892,-0.095406));

不使用 KNN 的浮点向量(仅存储)

你也可以创建没有 KNN 配置的 float_vector 属性。在这种模式下,向量被存储但不能用于向量搜索操作。

你可以做到:

  • 存储向量数据
  • UPDATE float_vector 值(与 KNN 不同,此时可以使用 UPDATE

你不能做到:

  • 执行 KNN 搜索或向量相似性搜索
  • 使用向量进行任何搜索操作
  • 通过 float_vector 值进行过滤

使用场景

  • 在配置KNN之前临时存储向量数据
  • 用于后续与KNN一起使用的暂存数据
  • 存储不需要搜索功能的向量
‹›
  • 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);

CREATE TABLE products(title text, product_codes mva);

它支持过滤和聚合,但不支持排序。过滤可以通过至少一个元素通过(使用 ANY())或所有元素 (ALL()) 来完成。

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

可以提取诸如最小最大元素以及列表长度等信息。以下示例展示了如何按多值属性的最小元素进行排序。

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

当按多值属性分组时,一个文档将贡献给与该文档关联的不同值数量相同的多个组。例如,如果一个集合恰好包含一个文档,其'product_codes'多值属性的值为5、7和11,那么按'product_codes'分组将产生3个组,COUNT(*)等于1,GROUPBY()键值分别为5、7和11。另外请注意,按多值属性分组可能导致结果集中出现重复文档,因为每个文档可以参与多个组。

‹›
  • 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)

作为多值属性值插入的数字顺序不会被保留。值在内部以排序集合的形式存储。

‹›
  • 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)

多值大整数

一种允许存储可变长度64位有符号整数列表的数据类型。其功能与多值整数相同。

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

CREATE TABLE products(title text, values mva64);

列式属性特性

当使用列式存储时,可以为属性指定以下特性。

fast_fetch

默认情况下,Manticore 列式存储以列式方式存储所有属性,同时也在特殊的文档存储中按行存储。这使得像 SELECT * FROM ... 这样的查询能够快速执行,尤其是在一次获取大量记录时。但是,如果您确定不需要此功能或希望节省磁盘空间,可以在创建表时通过指定 fast_fetch='0' 来禁用它,或者(如果您在配置中定义表)使用 columnar_no_fast_fetch,如下例所示。

‹›
  • 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: January 28, 2026