Manticore Search 支持为每个文档添加由机器学习模型生成的嵌入,然后对其执行最近邻搜索。这让你可以构建相似性搜索、推荐、语义搜索,以及基于 NLP 算法的相关性排序等功能,还包括图像、视频和声音搜索。
要将 KNN 向量搜索与全文搜索结合以获得更好的相关性,请参阅 混合搜索。
嵌入是一种将文本、图像或声音等数据表示为高维空间中向量的方法。这些向量的设计目标是让它们之间的距离能够反映所代表数据的相似度。这个过程通常会使用词嵌入算法(例如 Word2Vec、BERT)处理文本,或使用神经网络处理图像。向量空间具有高维特性,每个向量包含许多分量,因此能够表示对象之间复杂而细微的关系。它们的相似度通过这些向量之间的距离来衡量,通常使用欧氏距离或余弦相似度等方法。
Manticore Search 使用 HNSW 库支持 k 近邻(KNN)向量搜索。该功能属于 Manticore Columnar Library。
要运行 KNN 搜索,首先必须配置你的表。浮点向量和 KNN 搜索仅支持实时表(不支持普通表)。表中需要至少有一个 float_vector 属性,它充当数据向量。你需要指定以下属性:
-
knn_type:必填设置;目前仅支持hnsw。 -
knn_dims:必填设置,用于指定被索引向量的维度。 -
hnsw_similarity:必填设置,用于指定 HNSW 索引使用的距离函数。可接受的值有:L2- 平方 L2IP- 内积COSINE- 余弦相似度
注意: 当使用
COSINE相似度时,向量会在插入时自动归一化。这意味着存储的向量值可能与原始输入值不同,因为它们会被转换为单位向量(数学长度/模长为 1.0 的向量),以便高效计算余弦相似度。该归一化过程会保留向量方向,同时标准化其长度。 -
hnsw_m:可选设置,定义图中最大出边数。默认值为 16。 -
hnsw_ef_construction:可选设置,定义构建时间与精度之间的权衡。默认值为 200。
注意:在多核主机上,RT chunk 保存、
OPTIMIZE TABLE/ 自动优化 chunk 合并,以及ALTER TABLE ... ADD/DROP/REBUILDKNN 重建期间的 HNSW 图构建默认会并行运行;工作线程数由 searchd 设置knn_parallel_build控制(将其设为1可强制走串行路径)。这只影响构建阶段性能。由于并行 HNSW 构建可能以不同顺序插入向量,生成的图可能不会与串行构建在位级别完全一致。
- SQL
- JSON
- Config
create table test ( title text, image_vector float_vector knn_type='hnsw' knn_dims='4' hnsw_similarity='l2' );POST /sql?mode=raw -d "create table test ( title text, image_vector float_vector knn_type='hnsw' knn_dims='4' hnsw_similarity='l2' )"table test_vec {
type = rt
...
rt_attr_float_vector = image_vector
knn = {"attrs":[{"name":"image_vector","type":"hnsw","dims":4,"hnsw_similarity":"L2","hnsw_m":16,"hnsw_ef_construction":200}]}
}注意: 关于普通模式下的自动嵌入,请参见下面的示例,其中展示了如何在 knn 配置中使用 model_name 和 from 参数。
Query OK, 0 rows affected (0.01 sec)[
{
"total": 0,
"error": "",
"warning": ""
}
]处理向量数据最简单的方法是使用自动嵌入。使用此功能时,你创建一个带有 MODEL_NAME 和 FROM 参数的表,然后只需插入文本数据即可,Manticore 会自动为你生成嵌入。
创建用于自动嵌入的表时,请指定:
MODEL_NAME:要使用的嵌入模型FROM:用于生成嵌入的字段(留空表示所有文本/字符串字段)API_KEY:远程模型(OpenAI、Voyage、Jina)必需。API 密钥会在建表期间通过发起真实 API 请求进行验证。API_URL:可选。自定义 API 端点 URL。如果未指定,则使用默认提供方端点(例如 OpenAI 使用https://api.openai.com/v1/embeddings)。API_TIMEOUT:可选。API 请求的 HTTP 超时时间,单位为秒。默认值为 10 秒。设为'0'可使用默认超时。此设置同时适用于建表期间的验证请求和 INSERT 操作期间的嵌入生成。
对于远程模型,MODEL_NAME 可以写成两种形式:
- 传统的带提供方前缀形式:
openai/text-embedding-ada-002、voyage/voyage-3.5-lite、jina/jina-embeddings-v4 - 用于自定义端点的显式提供方标识形式:
openai:text-embedding-ada-002、openai:openai/text-embedding-ada-002、voyage:custom-model、jina:custom-model
当你把 provider:model 形式与 API_URL 一起使用时,冒号前的部分只用于选择请求格式。冒号后的部分会原样发送到远程端点。这对 OpenAI 兼容网关很有用,例如 OpenRouter 或 LiteLLM。
支持的嵌入模型:
| 模型类型 | 示例 | 需要 API 密钥 | 说明 |
|---|---|---|---|
| ONNX(推荐) | Xenova/all-MiniLM-L6-v2 |
否 | 来自任何提供 .onnx 文件的 Hugging Face 仓库的本地模型。运行在 Manticore 高速的 ONNX Runtime 后端上。浏览列表:feature-extraction ONNX 模型。 |
| Sentence Transformers | sentence-transformers/all-MiniLM-L6-v2 |
否 | 基于 BERT 的本地模型,会自动下载。仍然支持 - 在可用时优先使用上面的 ONNX。 |
| Qwen | Qwen/Qwen3-Embedding-0.6B |
否 | 本地 Qwen 系列模型 |
| Llama | TinyLlama/TinyLlama-1.1B-Chat-v1.0 |
否 | 本地 Llama 系列模型 |
| Mistral | Locutusque/TinyMistral-248M-v2 |
否 | 本地 Mistral 系列模型 |
| Gemma | h2oai/embeddinggemma-300m |
否 | 本地 Gemma 系列模型 |
| OpenAI | openai/text-embedding-ada-002 或 openai:text-embedding-ada-002 |
是 | API_KEY='***' |
| Voyage | voyage/voyage-3.5-lite 或 voyage:voyage-3.5-lite |
是 | API_KEY='***' |
| Jina | jina/jina-embeddings-v4 或 jina:jina-embeddings-v4 |
是 | API_KEY='***' |
本地模型格式要求:
- 必须以
safetensors格式保存(仅单文件) - 支持的系列:Qwen、Llama、Mistral、Gemma
- 已测试模型:
TinyLlama/TinyLlama-1.1B-Chat-v1.0、Locutusque/TinyMistral-248M-v2、Qwen/Qwen3-Embedding-0.6B、h2oai/embeddinggemma-300m - 其他
safetensors模型也可能可用,但不作保证
关于配置 float_vector 属性的更多信息,请参见这里。
- SQL
- Config
使用本地 ONNX 模型 - 推荐(无需 API key)
CREATE TABLE products (
title TEXT,
description TEXT,
embedding_vector FLOAT_VECTOR KNN_TYPE='hnsw' HNSW_SIMILARITY='l2'
MODEL_NAME='Xenova/all-MiniLM-L6-v2' FROM='title'
);使用 sentence-transformers(无需 API key;走 Candle 路径 - 在可用时优先使用上面的 ONNX)
CREATE TABLE products_st (
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' CACHE_PATH='/opt/homebrew/var/manticore/.cache/manticore'
);使用 OpenAI(需要 API_KEY 参数)
CREATE TABLE products_openai (
title TEXT,
description TEXT,
embedding_vector FLOAT_VECTOR KNN_TYPE='hnsw' HNSW_SIMILARITY='l2'
MODEL_NAME='openai/text-embedding-ada-002' FROM='title,description' API_KEY='...'
);使用 OpenAI 搭配自定义 API URL 和超时设置(可选)
CREATE TABLE products_openai_custom (
title TEXT,
description TEXT,
embedding_vector FLOAT_VECTOR KNN_TYPE='hnsw' HNSW_SIMILARITY='l2'
MODEL_NAME='openai:text-embedding-ada-002' FROM='title,description'
API_KEY='***' API_URL='https://custom-api.example.com/v1/embeddings' API_TIMEOUT='30'
);使用期望提供方限定模型 ID 的 OpenAI 兼容网关
CREATE TABLE products_openrouter (
title TEXT,
description TEXT,
embedding_vector FLOAT_VECTOR KNN_TYPE='hnsw' HNSW_SIMILARITY='l2'
MODEL_NAME='openai:openai/text-embedding-ada-002' FROM='title,description'
API_KEY='***' API_URL='https://openrouter.ai/api/v1/embeddings' API_TIMEOUT='30'
);使用所有文本字段生成嵌入(FROM 为空)
CREATE TABLE products_all (
title TEXT,
description TEXT,
embedding_vector FLOAT_VECTOR KNN_TYPE='hnsw' HNSW_SIMILARITY='l2'
MODEL_NAME='Xenova/all-MiniLM-L6-v2' FROM=''
);table products {
type = rt
path = /path/to/products
rt_field = title
rt_field = description
rt_attr_float_vector = embedding_vector
knn = {"attrs":[{"name":"embedding_vector","type":"hnsw","hnsw_similarity":"L2","hnsw_m":16,"hnsw_ef_construction":200,"model_name":"Xenova/all-MiniLM-L6-v2","from":"title"}]}
}在普通模式下使用带 API 密钥的 OpenAI:
table products_openai {
type = rt
path = /path/to/products_openai
rt_field = title
rt_field = description
rt_attr_float_vector = embedding_vector
knn = {"attrs":[{"name":"embedding_vector","type":"hnsw","hnsw_similarity":"L2","hnsw_m":16,"hnsw_ef_construction":200,"model_name":"openai/text-embedding-ada-002","from":"title,description","api_key":"your-api-key-here"}]}
}使用所有文本字段(空 FROM):
table products_all {
type = rt
path = /path/to/products_all
rt_field = title
rt_field = description
rt_attr_float_vector = embedding_vector
knn = {"attrs":[{"name":"embedding_vector","type":"hnsw","hnsw_similarity":"L2","hnsw_m":16,"hnsw_ef_construction":200,"model_name":"Xenova/all-MiniLM-L6-v2","from":""}]}
}普通模式重要说明:
- 使用
model_name时,不能指定dims- 模型会自动决定向量维度。dims和model_name参数互斥。 - 当不使用
model_name(手动插入向量)时,必须指定dims来说明向量维度。 from参数指定用于生成嵌入的字段(以逗号分隔的列表,或留空字符串表示所有文本/字符串字段)。使用model_name时必须提供此参数。- 对于基于 API 的模型(OpenAI、Voyage、Jina),请在 knn 配置中包含
api_key参数
使用自动嵌入时,你可以:
- 省略向量字段,让 Manticore 根据
FROM中列出的字段生成嵌入 - 为某一行显式提供你自己的向量
- 提供
()以跳过生成并存储全零向量
如果你之后运行 ALTER TABLE ... REBUILD EMBEDDINGS,当前包含来自 () 的零向量的行也会被重新生成。
- SQL
- JSON
仅插入文本数据 - 嵌入会自动生成
INSERT INTO products (title) VALUES
('machine learning artificial intelligence'),
('banana fruit sweet yellow');插入用户提供的向量
INSERT INTO products (title, embedding_vector) VALUES
('machine learning artificial intelligence', (0.653448,0.192478,0.017971,0.339821));插入多个字段 - 如果 FROM='title,description',两者都会用于生成嵌入
INSERT INTO products_openai (title, description) VALUES
('smartphone', 'latest mobile device with advanced features'),
('laptop', 'portable computer for work and gaming');插入空向量(不自动生成;存储零向量)
INSERT INTO products (title, embedding_vector) VALUES
('no embedding item', ());仅插入文本数据 - 嵌入会自动生成
POST /sql?mode=raw -d "INSERT INTO products (title) VALUES ('machine learning artificial intelligence'),('banana fruit sweet yellow')"插入多个字段 - 如果 FROM='title,description',两者都会用于生成嵌入
POST /sql?mode=raw -d "INSERT INTO products_openai (title, description) VALUES ('smartphone', 'latest mobile device with advanced features'), ('laptop', 'portable computer for work and gaming')"插入空向量(文档被排除在向量搜索之外)
POST /sql?mode=raw -d "INSERT INTO products (title, embedding_vector) VALUES ('no embedding item', ())"搜索方式相同 - 提供查询文本,Manticore 会生成嵌入并找到相似文档:
- SQL
- JSON
SELECT id, knn_dist() FROM products WHERE knn(embedding_vector, 'machine learning');使用文本查询和自动嵌入
POST /search
{
"table": "products",
"knn": {
"field": "embedding_vector",
"query": "machine learning"
}
}直接使用向量查询
POST /search
{
"table": "products",
"knn": {
"field": "embedding_vector",
"query": [0.1, 0.2, 0.3, 0.4]
}
}+------+------------+
| id | knn_dist() |
+------+------------+
| 1 | 0.12345678 |
| 2 | 0.87654321 |
+------+------------+
2 rows in set (0.00 sec){
"took": 0,
"timed_out": false,
"hits": {
"total": 2,
"total_relation": "eq",
"hits": [
{
"_id": 1,
"_score": 1,
"_knn_dist": 0.12345678,
"_source": {
"title": "machine learning artificial intelligence"
}
},
{
"_id": 2,
"_score": 1,
"_knn_dist": 0.87654321,
"_source": {
"title": "banana fruit sweet yellow"
}
}
]
}
}或者,你也可以手动插入预先计算好的向量数据,确保它与创建表时指定的维度一致。你也可以插入空向量;这意味着该文档将被排除在向量搜索结果之外。
重要: 当使用 hnsw_similarity='cosine' 时,向量会在插入时自动归一化为单位向量(数学长度/模长为 1.0 的向量)。这种归一化会保留向量方向,同时标准化其长度,这对于高效计算余弦相似度是必需的。这意味着存储值会与你的原始输入值不同。
- SQL
- JSON
insert into test values ( 1, 'yellow bag', (0.653448,0.192478,0.017971,0.339821) ), ( 2, 'white bag', (-0.148894,0.748278,0.091892,-0.095406) );POST /insert
{
"table":"test_vec",
"id":1,
"doc": { "title" : "yellow bag", "image_vector" : [0.653448,0.192478,0.017971,0.339821] }
}
POST /insert
{
"table":"test_vec",
"id":2,
"doc": { "title" : "white bag", "image_vector" : [-0.148894,0.748278,0.091892,-0.095406] }
}Query OK, 2 rows affected (0.00 sec){
"table":"test",
"_id":1,
"created":true,
"result":"created",
"status":201
}
{
"table":"test",
"_id":2,
"created":true,
"result":"created",
"status":201
}现在,你可以在 SQL 或 JSON 格式中使用 knn 子句执行 KNN 搜索。两种接口支持相同的核心参数,无论你选择哪种格式,都能获得一致的体验:
- SQL:
select ... from <table name> where knn ( <field>, <query vector> [,<options>] ) - JSON:
POST /search { "table": "<table name>", "knn": { "field": "<field>", "query": "<text or vector>", "ef": <ef>, "rescore": <rescore>, "oversampling": <oversampling> } }
参数如下:
field:包含向量数据的 float vector 属性名称。k:已弃用选项。请改用查询limit。它用于指定单个 HNSW 索引应返回的文档数量。不过,最终结果中包含的文档总数可能会变化。例如,如果系统处理的是按磁盘 chunk 划分的实时表,每个 chunk 都可能返回k个文档,从而使总数超过指定的k(因为累计数量为num_chunks * k)。另一方面,如果在请求k个文档后,其中一些又根据特定属性被过滤掉,那么最终文档数量也可能少于k。需要注意的是,k参数不适用于 ramchunks。在 ramchunks 场景下,检索过程的工作方式不同,因此k参数对返回文档数量的影响不适用。query:(推荐参数)搜索查询,可以是:- 文本字符串:如果该字段配置了自动嵌入,则会自动转换为嵌入。如果该字段没有自动嵌入,则会返回错误。
- 向量数组:工作方式与
query_vector相同。
query_vector:(旧参数)作为数字数组的搜索向量。为向后兼容仍然支持。 注意: 同一请求中只能使用query或query_vector其中之一,不能同时使用。ef:搜索过程中使用的动态列表大小,可选。ef越大,搜索越准确,但速度越慢。默认值为 10。rescore:启用 KNN 重新评分(默认启用)。在 SQL 中设为0或在 JSON 中设为false可禁用重新评分。KNN 搜索在使用量化向量完成后(可能伴随过采样),会使用原始(全精度)向量重新计算距离并重新排序结果,以提高排序准确性。oversampling:设置一个因子(浮点值),在执行 KNN 搜索时将k乘以该因子,从而使用量化向量检索出比所需更多的候选结果。默认应用oversampling=3.0。如果启用了重新评分,这些候选结果之后可以重新评估。过采样也适用于非量化向量。由于它会增大k,进而影响 HNSW 索引的工作方式,因此可能会使结果精度略有变化。early_termination:启用或禁用 HNSW 图遍历期间的自适应提前终止。默认启用。设为 SQL 中的0或 JSON 中的false可禁用。详情参见提前终止。
文档总是按其与搜索向量的距离排序。你指定的任何附加排序条件都会在这个主排序条件之后应用。若要获取距离,有一个内置函数 knn_dist()。
- SQL
- JSON
select id, knn_dist() from test where knn ( image_vector, (0.286569,-0.031816,0.066684,0.032926), { ef=2000, oversampling=3.0, rescore=1 } );POST /search
{
"table": "test",
"knn":
{
"field": "image_vector",
"query": [0.286569,-0.031816,0.066684,0.032926],
"ef": 2000,
"rescore": true,
"oversampling": 3.0
}
}+------+------------+
| id | knn_dist() |
+------+------------+
| 1 | 0.28146550 |
| 2 | 0.81527930 |
+------+------------+
2 rows in set (0.00 sec){
"took":0,
"timed_out":false,
"hits":
{
"total":2,
"total_relation":"eq",
"hits":
[
{
"_id": 1,
"_score":1,
"_knn_dist":0.28146550,
"_source":
{
"title":"yellow bag",
"image_vector":[0.653448,0.192478,0.017971,0.339821]
}
},
{
"_id": 2,
"_score":1,
"_knn_dist":0.81527930,
"_source":
{
"title":"white bag",
"image_vector":[-0.148894,0.748278,0.091892,-0.095406]
}
}
]
}
}HNSW 索引必须完整加载到内存中才能执行 KNN 搜索,这可能导致较高的内存消耗。为了降低内存占用,可以应用标量量化 - 这是一种通过用有限数量的离散值表示每个分量(维度)来压缩高维向量的技术。Manticore 支持 8 位和 1 位量化,这意味着每个向量分量都会从 32 位浮点压缩为 8 位甚至 1 位,分别将内存占用降低 4 倍或 32 倍。这些压缩表示还可以加快距离计算,因为更多的向量分量可以在单条 SIMD 指令中处理。虽然标量量化会引入一定的近似误差,但它通常是在搜索精度与资源效率之间值得接受的权衡。若要获得更高精度,可以将量化与重新评分和过采样结合使用:检索出的候选数量会多于请求数量,然后使用原始 32 位浮点向量重新计算这些候选的距离。
支持的量化类型包括:
8bit:每个向量分量都会量化为 8 位。1bit:每个向量分量都会量化为 1 位。这里使用非对称量化,查询向量量化为 4 位,存储向量量化为 1 位。与更简单的方法相比,这种方式提供了更高的精度,但会带来一定的性能权衡。1bitsimple:每个向量分量都会量化为 1 位。该方法比1bit更快,但通常精度更低。
- SQL
- JSON
create table test ( title text, image_vector float_vector knn_type='hnsw' knn_dims='4' hnsw_similarity='l2' quantization='1bit');POST /sql?mode=raw -d "create table test ( title text, image_vector float_vector knn_type='hnsw' knn_dims='4' hnsw_similarity='l2' quantization='1bit')"Query OK, 0 rows affected (0.01 sec)[
{
"total": 0,
"error": "",
"warning": ""
}
]注意:按 id 查找相似文档需要 Manticore Buddy。如果无法工作,请确认已安装 Buddy。
根据唯一 ID 查找与某个文档相似的文档是一个常见任务。例如,当用户查看某个特定条目时,Manticore Search 可以高效地识别并显示在向量空间中与之最相似的一组条目。做法如下:
- SQL:
select ... from <table name> where knn ( <field>, <k>, <document id> ) - JSON:
POST /search { "table": "<table name>", "knn": { "field": "<field>", "doc_id": <document id>, "k": <k> } }
参数如下:
field:包含向量数据的 float vector 属性名称。k:表示要返回的文档数量,是分层可导航小世界(HNSW)索引的关键参数。它指定单个 HNSW 索引应返回的文档数量。不过,最终结果中包含的文档总数可能会变化。例如,如果系统处理的是按磁盘 chunk 划分的实时表,每个 chunk 都可能返回k个文档,从而使总数超过指定的k(因为累计数量为num_chunks * k)。另一方面,如果在请求k个文档后,其中一些又根据特定属性被过滤掉,那么最终文档数量也可能少于k。需要注意的是,k参数不适用于 ramchunks。在 ramchunks 场景下,检索过程的工作方式不同,因此k参数对返回文档数量的影响不适用。document id:用于 KNN 相似度搜索的文档 ID。
- SQL
- JSON
select id, knn_dist() from test where knn ( image_vector, 5, 1 );POST /search
{
"table": "test",
"knn":
{
"field": "image_vector",
"doc_id": 1,
"k": 5
}
}+------+------------+
| id | knn_dist() |
+------+------------+
| 2 | 0.81527930 |
+------+------------+
1 row in set (0.00 sec){
"took":0,
"timed_out":false,
"hits":
{
"total":1,
"total_relation":"eq",
"hits":
[
{
"_id": 2,
"_score":1643,
"_knn_dist":0.81527930,
"_source":
{
"title":"white bag",
"image_vector":[-0.148894,0.748278,0.091892,-0.095406]
}
}
]
}
}- SQL
- JSON
select id, knn_dist() from test where knn ( image_vector, 5, (0.286569,-0.031816,0.066684,0.032926) ) and match('white') and id < 10;POST /search
{
"table": "test",
"knn":
{
"field": "image_vector",
"query": [0.286569,-0.031816,0.066684,0.032926],
"k": 5
},
"query":
{
"bool":
{
"must":
[
{ "match": {"_all":"white"} },
{ "range": { "id": { "lt": 10 } } }
]
}
}
}+------+------------+
| id | knn_dist() |
+------+------------+
| 2 | 0.81527930 |
+------+------------+
1 row in set (0.00 sec){
"took":0,
"timed_out":false,
"hits":
{
"total":1,
"total_relation":"eq",
"hits":
[
{
"_id": 2,
"_score":1643,
"_knn_dist":0.81527930,
"_source":
{
"title":"white bag",
"image_vector":[-0.148894,0.748278,0.091892,-0.095406]
}
}
]
}
}当将 KNN 向量搜索与属性过滤结合时,Manticore 支持两种策略,它们的区别在于过滤条件相对于 HNSW 图遍历的应用时机。
-
预过滤(默认;SQL 中为
prefilter=1,JSON 中为"prefilter": true,默认)会把过滤条件直接传入 HNSW 遍历过程。每个候选项在加入结果堆之前都会先检查是否满足过滤条件 - 只有匹配的文档才会计入最终的k个结果。这减少了无效的距离计算,并保证最终返回恰好k个匹配文档(前提是确实存在k个匹配文档)。 -
后过滤(SQL 中为
prefilter=0,JSON 中为"prefilter": false)会先在完整数据集上执行 KNN 搜索,然后再对结果应用过滤条件。这种方式安全且可预测:HNSW 图在不受干扰的情况下遍历,过滤器只影响哪些结果会返回给客户端。缺点是图可能会在最终会被丢弃的候选项上耗费精力。当过滤条件非常严格、只匹配极少部分文档时,返回的k个结果可能会明显少于请求数量,因为大多数 KNN 候选都会被过滤掉。
在内部,Manticore 在预过滤中使用了基于 ACORN-1 的算法。朴素的预过滤只会简单跳过不匹配的节点,这会有丢失连接原本分离部分 HNSW 图的“桥接”节点的风险,从而在过滤条件越来越严格时导致召回率崩溃。ACORN-1 避免了这一点:当某个节点不满足过滤条件时,它的邻居仍会被加入探索队列。这样遍历就可以绕过被过滤掉的节点,并维持图的连通性。当通过过滤条件的文档少于总文档数的 60% 时,会自动启用 ACORN-1 探索。
自动暴力回退: 当启用预过滤时,Manticore 会估算在过滤后的子集上执行暴力距离扫描是否比遍历 HNSW 图更便宜。该估算会比较 HNSW 预计访问的节点数与通过过滤的文档数。如果过滤后的集合足够小,直接扫描更快,Manticore 会自动切换到暴力方式,完全跳过 HNSW。这样即使在极高选择性条件下,也能保证正确性和良好性能。
- SQL
- JSON
-- prefilter (default): filter applied during HNSW traversal (ACORN-1 used automatically)
SELECT id, knn_dist() FROM test
WHERE knn ( image_vector, (0.286569,-0.031816,0.066684,0.032926) )
AND price < 100;
-- postfilter: KNN runs over full dataset, filter applied to results
SELECT id, knn_dist() FROM test
WHERE knn ( image_vector, (0.286569,-0.031816,0.066684,0.032926), { prefilter=0 } )
AND price < 100;// prefilter (default): filter applied during HNSW traversal
POST /search
{
"table": "test",
"knn": {
"field": "image_vector",
"query": [0.286569,-0.031816,0.066684,0.032926]
},
"query": {
"range": { "price": { "lt": 100 } }
}
}
// postfilter: filter applied after KNN search
POST /search
{
"table": "test",
"knn": {
"field": "image_vector",
"query": [0.286569,-0.031816,0.066684,0.032926],
"prefilter": false
},
"query": {
"range": { "price": { "lt": 100 } }
}
}默认情况下,Manticore 在 HNSW 图遍历期间使用自适应提前终止算法。它不会始终探索由 ef 定义的完整候选集,而是监控新候选项改进结果集的速率,并在该速率持续低于阈值时提前停止。这样可以减少距离计算次数,同时不会显著影响结果质量。
提前终止默认启用,并且当 k 为 10 或更少时会自动禁用,因为对于这么小的结果集,该算法的开销不值得。性能收益会随着 k 增大而提升 - 结果集越大,通过提前停止就能节省越多距离计算。
请注意,过采样会乘大 HNSW 遍历期间使用的有效 k,因此提前终止也会从过采样中受益:更高的有效 k 意味着可能跳过更多候选项。
若要显式控制提前终止,请使用 early_termination 选项:
- SQL
- JSON
-- disable early termination
SELECT id, knn_dist() FROM test WHERE knn ( image_vector, (0.286569,-0.031816,0.066684,0.032926), { ef=200, early_termination=0 } );
-- enable early termination explicitly (default)
SELECT id, knn_dist() FROM test WHERE knn ( image_vector, (0.286569,-0.031816,0.066684,0.032926), { ef=200, early_termination=1 } );POST /search
{
"table": "test",
"knn":
{
"field": "image_vector",
"query": [0.286569,-0.031816,0.066684,0.032926],
"ef": 200,
"early_termination": false
}
}何时应禁用提前终止:
- 当结果集精度至关重要,且你无法接受超出 HNSW 已提供范围的任何近似时。
- 当使用较低的
k值(大约 30 或更少)时,此时提前终止带来的性能收益很小,但可能降低精度。
混合搜索在一个查询中结合了全文(BM25)搜索与KNN向量搜索,使用倒数排名融合(RRF)融合结果。这利用了两种检索方法的优势:BM25的关键词精确性与向量相似度的语义理解。
全文搜索擅长精确关键词匹配和稀有术语,但会遗漏概念上相似的内容。向量搜索捕捉语义含义,但在模糊查询中可能产生噪声。混合搜索结合两者,因此在任一或两者信号中得分高的文档会被展示。
RRF是一种基于排名的融合算法。它基于排名位置而非原始分数进行操作,避免了需要归一化不兼容的分数尺度(BM25分数是无界的;KNN距离有不同的尺度)。
RRF_score(d) = SUM over all result sets r: weight_r / (rank_constant + rank_r(d))
其中:
d是一个文档rank_r(d)是文档在结果集r中的1-based位置(按该检索器的分数排序)rank_constant是一个平滑常数(默认:60,可通过rank_constant选项配置)weight_r是每个检索器的可选权重(默认:1.0)
如果文档未出现在特定结果集中,该集合对该文档的贡献为0。
rank_constant=60是默认值。- 较低的值(例如10)会放大排名靠前项目的差异。
- 较高的值(例如100)会使排名间的影响力更均匀分布。
在 WHERE 子句中结合 MATCH(...) 和 KNN(...),并使用 OPTION fusion_method='rrf':
- SQL
- JSON
SELECT id, hybrid_score()
FROM t
WHERE match('machine learning')
AND knn(vec, (0.1, 0.1, 0.1, 0.1))
OPTION fusion_method='rrf';POST /search
{
"table": "t",
"knn": {
"field": "vec",
"query_vector": [0.1, 0.1, 0.1, 0.1]
},
"query": { "match": { "title": "machine learning" } },
"options": { "fusion_method": "rrf" }
}这会将文本搜索和 KNN 搜索作为独立的并行子查询运行,然后使用 RRF 融合结果。如果没有 fusion_method='rrf',查询会作为常规 KNN 搜索运行,仅通过文本匹配进行过滤(预混合行为)。
在该预混合模式下,KNN 排名仍优先。如果 knn_dist() 可用且未显式按其排序,Manticore 会在排序顺序前添加 knn_dist() ASC。实际上,ORDER BY weight() DESC 成为次要的平局打破者,而非全局 BM25 排序。
hybrid_score()- RRF 融合分数(仅在混合查询中可用)weight()- BM25 文本匹配分数knn_dist()- 向量距离(如果有多个 KNN 子查询,则取最小值)
| 选项 | 类型 | 默认值 | 描述 |
|---|---|---|---|
fusion_method |
字符串 | (无) | 设置为 'rrf' 以启用混合搜索。必需。 |
rank_constant |
整数 | 60 | RRF 公式中的平滑常数 |
window_size |
整数 | 0(自动) | 每个子查询在融合前检索的结果数量。当为0时,从 KNN k(带过采样)和查询 LIMIT 自动计算 |
fusion_weights |
元组 | (全部为1.0) | RRF 评分中每个子查询的权重 |
- SQL
- JSON
-- Default rank_constant=60 (gentler ranking)
SELECT id, hybrid_score() FROM t
WHERE match('machine learning') AND knn(vec, (0.1, 0.1, 0.1, 0.1))
OPTION fusion_method='rrf';
-- rank_constant=10 (sharper top-rank differences)
SELECT id, hybrid_score() FROM t
WHERE match('machine learning') AND knn(vec, (0.1, 0.1, 0.1, 0.1))
OPTION fusion_method='rrf', rank_constant=10;POST /search
{
"table": "t",
"knn": { "field": "vec", "query_vector": [0.1, 0.1, 0.1, 0.1] },
"query": { "match": { "title": "machine learning" } },
"options": { "fusion_method": "rrf", "rank_constant": 10 }
}标准 WHERE 过滤器可与混合搜索一起使用。过滤器应用于文本和 KNN 子查询:
- SQL
- JSON
SELECT id, category, hybrid_score()
FROM t
WHERE match('machine learning')
AND knn(vec, (0.1, 0.1, 0.1, 0.1))
AND category = 1
OPTION fusion_method='rrf';POST /search
{
"table": "t",
"knn": { "field": "vec", "query_vector": [0.1, 0.1, 0.1, 0.1] },
"query": {
"bool": {
"must": [
{ "match": { "title": "machine learning" } },
{ "equals": { "category": 1 } }
]
}
},
"options": { "fusion_method": "rrf" }
}默认情况下,结果按 hybrid_score() DESC 排序。您可以覆盖此设置:
本节适用于真正的混合查询,即使用 OPTION fusion_method='rrf' 的查询。没有 fusion_method='rrf',包含 KNN(...) 的查询不会被融合,仍保持 KNN 优先,因此 ORDER BY weight() DESC 不会产生全局按权重排序的结果集。
- SQL
-- Sort by hybrid score ascending
SELECT id, hybrid_score() FROM t
WHERE match('machine learning') AND knn(vec, (0.1, 0.1, 0.1, 0.1))
ORDER BY hybrid_score() ASC
OPTION fusion_method='rrf';
-- Sort by text weight
SELECT id, weight() FROM t
WHERE match('machine learning') AND knn(vec, (0.1, 0.1, 0.1, 0.1))
ORDER BY weight() DESC, id ASC
OPTION fusion_method='rrf';
-- Sort by KNN distance
SELECT id, knn_dist() FROM t
WHERE match('machine learning') AND knn(vec, (0.1, 0.1, 0.1, 0.1))
ORDER BY knn_dist() ASC
OPTION fusion_method='rrf';如果文本查询未匹配任何文档,仅 KNN 结果会对 RRF 分数做出贡献:
SELECT id, hybrid_score() FROM t
WHERE match('xyznonexistent') AND knn(vec, (0.1, 0.1, 0.1, 0.1))
OPTION fusion_method='rrf';
-- Returns results ranked purely by KNN rank
单个混合查询可以将文本搜索与不同向量属性上的多个 KNN 搜索结合。所有内容通过 RRF 融合:
- SQL
- JSON
-- Three-way fusion: text + vec1 KNN + vec2 KNN
SELECT id, hybrid_score()
FROM t
WHERE match('machine learning')
AND knn(vec1, (0.1, 0.1, 0.1, 0.1))
AND knn(vec2, (1.0, 0.0, 0.0, 0.0))
OPTION fusion_method='rrf';
-- KNN-only fusion (no text), two vector searches
SELECT id, hybrid_score()
FROM t
WHERE knn(vec1, (0.1, 0.1, 0.1, 0.1))
AND knn(vec2, (1.0, 0.0, 0.0, 0.0))
OPTION fusion_method='rrf';POST /search
{
"table": "t",
"knn": [
{ "field": "vec1", "query_vector": [0.1, 0.1, 0.1, 0.1] },
{ "field": "vec2", "query_vector": [1.0, 0.0, 0.0, 0.0] }
],
"query": { "match": { "title": "machine learning" } },
"options": { "fusion_method": "rrf" }
}没有 fusion_method 的多个 KNN 搜索会产生错误。
默认情况下,所有子查询贡献相等(权重1.0)。要为文本与 KNN 搜索赋予不同的重要性,请使用 fusion_weights 并使用显式别名:
- SQL
- JSON
SELECT id, hybrid_score()
FROM t
WHERE match('machine learning') AS text
AND knn(vec1, (0.1, 0.1, 0.1, 0.1)) AS dense1
AND knn(vec2, (1.0, 0.0, 0.0, 0.0)) AS dense2
OPTION fusion_method='rrf',
fusion_weights=(text=0.7, dense1=0.2, dense2=0.1);POST /search
{
"table": "t",
"knn": [
{ "field": "vec1", "query_vector": [0.1, 0.1, 0.1, 0.1], "name": "dense1" },
{ "field": "vec2", "query_vector": [1.0, 0.0, 0.0, 0.0], "name": "dense2" }
],
"query": { "match": { "title": "machine learning" } },
"options": {
"fusion_method": "rrf",
"fusion_weights": { "query": 0.7, "dense1": 0.2, "dense2": 0.1 }
}
}SQL:
- 使用
AS alias对MATCH(...)和KNN(...)命名。没有隐式/默认别名。 - 省略的别名默认权重为1.0。
- 引用不存在的别名会产生错误。
JSON:
"query"是全文子查询的固定别名。- 每个 KNN 条目通过
"name"属性设置 KNN 别名。 - 命名为
"query"的 KNN 条目与文本别名冲突并产生错误。 fusion_weights中不支持隐式别名(无显式"name"的字段名)。
您可以仅为部分子查询指定权重;其余默认为1.0:
-- Only boost text, KNN searches default to weight 1.0
SELECT id, hybrid_score()
FROM t
WHERE match('machine learning') AS text
AND knn(vec1, (0.1, 0.1, 0.1, 0.1)) AS dense1
AND knn(vec2, (1.0, 0.0, 0.0, 0.0)) AS dense2
OPTION fusion_method='rrf', fusion_weights=(text=2.0);
对于在 float_vector 属性上配置了自动嵌入的表,hybrid_match() 提供了一个简写,可自动从单个查询字符串运行文本和 KNN 搜索:
- SQL
-- Explicit vector field
SELECT id, hybrid_score() FROM t WHERE hybrid_match('machine learning', vec);
-- Auto-detect vector field (requires exactly one auto-embedding attribute)
SELECT id, hybrid_score() FROM t WHERE hybrid_match('machine learning');
-- With custom k and rank_constant
SELECT id, hybrid_score() FROM t
WHERE hybrid_match('machine learning', vec, {k=3})
OPTION rank_constant=10;
-- With attribute filter
SELECT id, hybrid_score() FROM t
WHERE hybrid_match('machine learning', vec) AND category=1;hybrid_match() 自动执行以下操作:
- 将文本查询作为 BM25 全文搜索运行
- 从同一文本字符串生成嵌入
- 使用该嵌入运行 KNN 搜索
- 通过 RRF 融合结果
要求:向量属性必须为自动嵌入配置model_name和from。如果没有配置,hybrid_match()将返回错误。
对于具有自动嵌入的表,JSON中可以使用"hybrid"属性作为简写:
- JSON
POST /search
{
"table": "hj",
"hybrid": { "query": "machine learning" }
}
POST /search
{
"table": "hj",
"hybrid": { "query": "machine learning", "field": "vec" }
}
POST /search
{
"table": "hj",
"hybrid": { "query": "machine learning" },
"options": { "rank_constant": 10 }
}"hybrid"属性不能与"knn"一起使用。
当向量属性具有自动嵌入时,可以在knn对象中使用"query"(字符串)代替"query_vector"(数组):
POST /search
{
"table": "ht",
"knn": { "field": "vec", "query": "machine learning", "k": 5 },
"query": { "match": { "title": "machine learning" } },
"options": { "fusion_method": "rrf" }
}
字符串会在查询时自动嵌入。如果没有配置自动嵌入,这将返回错误。
内部地,混合查询会被拆分为N+1个并行子查询:
- 任务0:全文(BM25)子查询(如果文本查询为空则跳过,以避免用全扫描结果污染RRF)
- 任务1..N:每个
knn(...)条目对应一个KNN子查询
所有子查询并发运行。在全部完成之后,RRF融合:
- 从每个子查询收集排序结果
- 对于每个文档,累积其出现在每个子查询中的RRF得分贡献
- 按融合后的RRF得分降序排序
- 将
knn_dist()设置为每个文档在所有KNN子查询中的最小距离 - 保留来自文本子查询的
weight()
会话式搜索让 Manticore Buddy 能基于已有的向量化表来回答问题。Buddy 先用 KNN 搜索检索最相关的行,再把这些行转换为上下文,最后把上下文和对话历史一起发送给 LLM。
它通过 SQL 进行管理,使用:
CREATE CHAT MODELSHOW CHAT MODELSDESCRIBE CHAT MODELDROP CHAT MODELCALL CHAT
你需要一张向量化表和一个 LLM 提供方。下面会说明表的要求。提供方凭据可以在 CREATE CHAT MODEL 中通过 api_key 设置,也可以通过匹配的环境变量提供,例如 OPENAI_API_KEY。
当 CALL CHAT 运行时,Buddy 会按以下顺序构建检索增强答案:
- Buddy 加载聊天模型。
- Buddy 加载所提供 conversation UUID 对应的对话历史。如果没有提供 UUID,它会创建一个。
- Buddy 检查目标表并选择一个
FLOAT_VECTOR字段。 - LLM 决定如何处理消息:重新搜索、基于之前的搜索上下文回答,或不依赖检索直接回答。
- 在需要检索时,Buddy 使用选定的向量字段执行 KNN 搜索。
- Buddy 根据向量字段的
from='...'源字段构建 LLM 上下文。 - 配置的 LLM 生成答案。
- Buddy 将用户消息和助手回复保存到对话历史中。
CALL CHAT 的第五个参数在内部称为 fields,但在会话式搜索里它指的是 knn(...) 使用的向量字段,而不是要返回的字段列表。Buddy 会用 SELECT * 选出行,然后从 sources 载荷中移除向量列,因此响应不会包含大量 embedding 值。
表中必须至少有一个为 自动嵌入 配置的 FLOAT_VECTOR 字段。向量字段必须包含 from='...',因为 Buddy 会使用这些源字段作为 LLM 上下文。
下面的示例使用 onnx-models/all-MiniLM-L12-v2-onnx,它通过推荐的 ONNX 路径运行,不需要 embedding API key。
- SQL
CREATE TABLE docs (
id BIGINT,
title TEXT,
content TEXT,
embedding FLOAT_VECTOR
knn_type='hnsw'
hnsw_similarity='cosine'
model_name='onnx-models/all-MiniLM-L12-v2-onnx'
from='title,content'
) TYPE='rt';
INSERT INTO docs(id, title, content) VALUES
(1, 'Vector search', 'Vector search compares embeddings to find semantically similar documents.'),
(2, 'Full-text search', 'Full-text search matches terms and phrases in indexed text.');如果 CALL CHAT 没有指定向量字段,Buddy 会使用表定义中找到的第一个 FLOAT_VECTOR 字段。
使用 CREATE CHAT MODEL 来保存 LLM 提供方、模型 ID 和检索设置。
- SQL
CREATE CHAT MODEL assistant (
model='openai:gpt-4o-mini'
);你也可以设置提供方选项和检索限制:
- SQL
CREATE CHAT MODEL support_assistant (
model='openai:gpt-4o-mini',
api_key='your-provider-api-key',
base_url='http://host.docker.internal:8787/v1',
timeout=60,
retrieval_limit=5,
max_document_length=3000
);常见选项:
| 选项 | 必需 | 说明 |
|---|---|---|
model |
是 | provider:model 格式的 LLM 模型 ID。 |
description |
否 | 保存的描述。 |
api_key |
否 | 传递给 llm 扩展的提供方 API key。 |
base_url |
否 | 提供方或代理的 base URL。 |
timeout |
否 | LLM 请求超时,1..65536。 |
retrieval_limit |
否 | 从 KNN 请求的文档数量,1..50;默认值是 5。 |
max_document_length |
否 | 单篇文档的上下文长度限制。0 表示不截断;100..65536 会截断;默认值是 2000。 |
聊天模型名称只能包含字母、数字和下划线。
model 选项必须使用 provider:model 格式:
model='openai:gpt-4o-mini'
如果提供方 key 已经可用在 Buddy 的环境中,则提供方的 api_key 是可选的。例如,Docker Compose 服务可以这样传递提供方 key:
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
如果没有在 CREATE CHAT MODEL 中设置 api_key,llm 扩展可以使用匹配的提供方环境变量。只有当你需要让这个模型使用不同的 key 时,才在聊天模型中设置 api_key。
CALL CHAT(
'query',
'table',
'model_name',
'conversation_uuid',
'vector_field'
);
参数只能按位置传递:
| 位置 | 参数 | 必需 | 说明 |
|---|---|---|---|
| 1 | query |
是 | 用户问题。 |
| 2 | table |
是 | 要搜索的表。 |
| 3 | model_name |
是 | 聊天模型名称。 |
| 4 | conversation_uuid |
否 | 现有对话 ID,或空字符串。 |
| 5 | fields / 向量字段 |
否 | knn(...) 中使用的 FLOAT_VECTOR 字段。 |
表参数必须是普通表标识符,也可以可选地写成 database.table。向量字段参数必须是普通字段标识符。
使用 CALL CHAT 时,传入查询、表和聊天模型。
- SQL
CALL CHAT(
'What is vector search?',
'docs',
'assistant'
);要继续同一段对话,请传入相同的 conversation UUID:
- SQL
CALL CHAT(
'Can you explain it with an example?',
'docs',
'assistant',
'docs-chat-001'
);要搜索特定的向量字段,请将其作为第五个参数传入:
- SQL
CALL CHAT(
'Find documents where the title is about vector search',
'docs',
'assistant',
'',
'title_embedding'
);当提供第五个参数时,Buddy 会检查该字段是否存在且类型为 FLOAT_VECTOR。如果省略该参数,Buddy 会从 SHOW CREATE TABLE 中检测第一个 FLOAT_VECTOR 字段。
当 Buddy 需要检索时,它会在选定的向量字段上执行 KNN 搜索,并返回最多 retrieval_limit 行。默认距离阈值为 0.8。
Buddy 将检索到的行作为 LLM 上下文。同样的行会在 sources 中返回,其中包含 knn_dist,并移除了 FLOAT_VECTOR 列。
max_document_length 限制了每个源行可以发送给 LLM 的文本量。使用 0 可禁用截断;否则请使用 100 到 65536 之间的值。
CALL CHAT 返回一行:
| 列 | 说明 |
|---|---|
conversation_uuid |
现有或生成的对话 ID。 |
user_query |
原始用户查询。 |
search_query |
用于检索的独立搜索查询。 |
response |
LLM 答案。 |
sources |
包含检索到的源行的 JSON 字符串。 |
响应结构示例:
{
"conversation_uuid": "docs-chat-001",
"user_query": "What is vector search?",
"search_query": "vector search, embeddings, similarity search",
"response": "Vector search finds similar items by comparing embeddings...",
"sources": "[{\"id\":1,\"title\":\"Vector Search\",\"content\":\"...\",\"knn_dist\":0.12}]"
}
向量字段不会包含在 sources 中。
列出模型:
- SQL
SHOW CHAT MODELS;查看模型详情:
- SQL
DESCRIBE CHAT MODEL assistant;删除模型:
- SQL
DROP CHAT MODEL assistant;安全删除:
- SQL
DROP CHAT MODEL IF EXISTS assistant;SHOW CHAT MODELS 会返回 name、model 和 created_at。DESCRIBE CHAT MODEL 会返回 property 和 value;已保存的 API key 会显示为 HIDDEN。
删除聊天模型时也会删除该模型的对话历史表。对话历史按模型单独存储,并以 30 天 TTL 写入。
ALTER TABLE table ADD COLUMN column_name [{INTEGER|INT|BIGINT|FLOAT|BOOL|MULTI|MULTI64|JSON [secondary_index='1']|STRING|TEXT [INDEXED [ATTRIBUTE]]|TIMESTAMP|FLOAT_VECTOR [KNN options]}] [engine='columnar']
ALTER TABLE table DROP COLUMN column_name
ALTER TABLE table MODIFY COLUMN column_name bigint
此功能仅支持为RT表一次添加一个字段,或将int列扩展为bigint。支持的数据类型包括:
int- 整数属性timestamp- 时间戳属性bigint- 大整数属性float- 浮点数属性bool- 布尔属性multi- 多值整数属性multi64- 多值bigint属性json- JSON 属性;使用secondary_index='1'为 JSON 创建二级索引string/text attribute/string attribute- 字符串属性text/text indexed stored/string indexed stored- 全文索引字段,原始值存储在docstore中text indexed/string indexed- 全文索引字段,仅索引(原始值不存储在docstore中)text indexed attribute/string indexed attribute- 全文索引字段 + 字符串属性(不将原始值存储在docstore中)text stored/string stored- 值仅存储在docstore中,不进行全文索引,也不是字符串属性float_vector- 向量属性。您可以使用与CREATE TABLE中相同的 KNN 和 auto-embedding 选项- 为任何属性(json除外)添加
engine='columnar'将使其存储在列式存储中
- ❗建议在
ALTER表之前备份表文件,以防突然断电或其他类似问题导致数据损坏。 - 添加列时无法查询表。
- 新创建的标量属性默认设置为
0。 - 新增的
float_vector列如果没有MODEL_NAME,则初始化为零向量。 - 如果添加带有
MODEL_NAME和FROM的float_vector列,ALTER TABLE ... ADD COLUMN期间现有行会自动嵌入。 - 指定
MODEL_NAME时,FROM是必需的。使用FROM=''从所有text字段和string属性中嵌入。 ALTER不适用于分布式表和无任何属性的表。- 不能删除
id列。 - 当删除一个既是全文字段又是字符串属性的字段时,第一次
ALTER DROP删除属性,第二次删除全文字段。 - 添加/删除全文字段仅在RT模式下支持。
- Example
mysql> desc rt;
+------------+-----------+
| Field | Type |
+------------+-----------+
| id | bigint |
| text | field |
| group_id | uint |
| date_added | timestamp |
+------------+-----------+
mysql> alter table rt add column test integer;
mysql> desc rt;
+------------+-----------+
| Field | Type |
+------------+-----------+
| id | bigint |
| text | field |
| group_id | uint |
| date_added | timestamp |
| test | uint |
+------------+-----------+
mysql> alter table rt drop column group_id;
mysql> desc rt;
+------------+-----------+
| Field | Type |
+------------+-----------+
| id | bigint |
| text | field |
| date_added | timestamp |
| test | uint |
+------------+-----------+
mysql> alter table rt add column title text indexed;
mysql> desc rt;
+------------+-----------+------------+
| Field | Type | Properties |
+------------+-----------+------------+
| id | bigint | |
| text | text | indexed |
| title | text | indexed |
| date_added | timestamp | |
| test | uint | |
+------------+-----------+------------+
mysql> alter table rt add column title text attribute;
mysql> desc rt;
+------------+-----------+------------+
| Field | Type | Properties |
+------------+-----------+------------+
| id | bigint | |
| text | text | indexed |
| title | text | indexed |
| date_added | timestamp | |
| test | uint | |
| title | string | |
+------------+-----------+------------+
mysql> alter table rt drop column title;
mysql> desc rt;
+------------+-----------+------------+
| Field | Type | Properties |
+------------+-----------+------------+
| id | bigint | |
| text | text | indexed |
| title | text | indexed |
| date_added | timestamp | |
| test | uint | |
+------------+-----------+------------+
mysql> alter table rt drop column title;
mysql> desc rt;
+------------+-----------+------------+
| Field | Type | Properties |
+------------+-----------+------------+
| id | bigint | |
| text | text | indexed |
| date_added | timestamp | |
| test | uint | |
+------------+-----------+------------+ALTER TABLE table ft_setting='value'[, ft_setting2='value']
您可以使用ALTER在RT模式下修改表的全文设置。但是,它只影响新文档,不影响现有文档。
示例:
- 创建一个具有全文字段和
charset_table的表,该表只允许3个可搜索字符:a、b和c。 - 然后我们插入文档'abcd'并通过查询
abcd找到它,d被忽略,因为它不在charset_table数组中 - 然后我们意识到,我们也希望
d可搜索,因此我们借助ALTER添加它 - 但相同的查询
where match('abcd')仍然显示它搜索的是abc,因为现有文档记住了charset_table的先前内容 - 然后我们添加另一个文档
abcd并再次搜索abcd - 现在它找到了两个文档,并且
show meta显示它使用了两个关键词:abc(用于查找旧文档)和abcd(用于新文档)。
- Example
mysql> create table rt(title text) charset_table='a,b,c';
mysql> insert into rt(title) values('abcd');
mysql> select * from rt where match('abcd');
+---------------------+-------+
| id | title |
+---------------------+-------+
| 1514630637682688054 | abcd |
+---------------------+-------+
mysql> show meta;
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| total | 1 |
| total_found | 1 |
| time | 0.000 |
| keyword[0] | abc |
| docs[0] | 1 |
| hits[0] | 1 |
+---------------+-------+
mysql> alter table rt charset_table='a,b,c,d';
mysql> select * from rt where match('abcd');
+---------------------+-------+
| id | title |
+---------------------+-------+
| 1514630637682688054 | abcd |
+---------------------+-------+
mysql> show meta
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| total | 1 |
| total_found | 1 |
| time | 0.000 |
| keyword[0] | abc |
| docs[0] | 1 |
| hits[0] | 1 |
+---------------+-------+
mysql> insert into rt(title) values('abcd');
mysql> select * from rt where match('abcd');
+---------------------+-------+
| id | title |
+---------------------+-------+
| 1514630637682688055 | abcd |
| 1514630637682688054 | abcd |
+---------------------+-------+
mysql> show meta;
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| total | 2 |
| total_found | 2 |
| time | 0.000 |
| keyword[0] | abc |
| docs[0] | 1 |
| hits[0] | 1 |
| keyword[1] | abcd |
| docs[1] | 1 |
| hits[1] | 1 |
+---------------+-------+您可以在RT模式下更改实时表的名称。
ALTER TABLE table_name RENAME new_table_name;
注意:重命名实时表需要Manticore Buddy。如果不起作用,请确保Buddy已安装。
- Example
ALTER TABLE table_name RENAME new_table_name;Query OK, 0 rows affected (0.00 sec)ALTER TABLE table RECONFIGURE
ALTER还可以在普通模式下重新配置RT表,以便配置文件中的新分词、词法分析和其他文本处理设置对新文档生效。注意,现有文档将保持不变。在内部,它会强制将当前RAM块保存为新的磁盘块,并调整表头,以便使用更新的全文设置对新文档进行分词。
- Example
mysql> show table rt settings;
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| settings | |
+---------------+-------+
1 row in set (0.00 sec)
mysql> alter table rt reconfigure;
Query OK, 0 rows affected (0.00 sec)
mysql> show table rt settings;
+---------------+----------------------+
| Variable_name | Value |
+---------------+----------------------+
| settings | morphology = stem_en |
+---------------+----------------------+
1 row in set (0.00 sec)ALTER TABLE table REBUILD SECONDARY
您还可以使用ALTER重建给定表中的二级索引。有时,二级索引可能对整个表或表中的一个或多个属性被禁用:
- 当属性更新时,其二级索引将被禁用。
- 如果Manticore加载了一个带有不再支持的旧版本二级索引的表,则整个表的二级索引将被禁用。
ALTER TABLE table REBUILD SECONDARY从属性数据重建二级索引并重新启用它们。
此外,旧版本的二级索引可能受支持,但会缺少某些功能。REBUILD SECONDARY可用于更新二级索引。
- Example
ALTER TABLE rt REBUILD SECONDARY;Query OK, 0 rows affected (0.00 sec)ALTER TABLE table REBUILD KNN
该命令重新处理表中的所有向量数据,并从头开始重建KNN索引。
- Example
ALTER TABLE rt REBUILD KNN;Query OK, 0 rows affected (0.00 sec)ALTER TABLE table REBUILD EMBEDDINGS column_name
此命令重新生成一个目标 float_vector 列的嵌入,该列配置了 MODEL_NAME 和 FROM。
在需要为现有嵌入列重新生成向量时使用此功能,例如在使用 ALTER TABLE ... ADD COLUMN 后稍后添加该列并希望重新处理行,或希望强制为所有行重新生成向量时。
重要行为:
- 列名是必填项。该命令一次仅重建一个嵌入列。
- 为该列中的所有行重新生成嵌入,而不仅仅是向量为零的行。
- 它还会覆盖那些手动插入向量的行,以及使用
()跳过生成并存储零向量的行。 - 目标列必须是带有嵌入模型配置的索引
float_vector。 - 允许
FROM='',表示“使用所有text字段和string属性”。
Manticore 不会持久化该列中当前向量是自动生成、由用户显式提供,还是从 () 创建的。如果你运行 REBUILD EMBEDDINGS,存储的值将从配置的 FROM 源为该列中的每一行重新生成,包括当前值为全零向量的行。
- Example
ALTER TABLE products ADD COLUMN embedding FLOAT_VECTOR KNN_TYPE='hnsw' HNSW_SIMILARITY='l2' MODEL_NAME='Xenova/all-MiniLM-L6-v2' FROM='title';
ALTER TABLE products REBUILD EMBEDDINGS embedding;Query OK, 0 rows affected (0.00 sec)当使用远程模型进行自动嵌入时,可以使用 ALTER 修改 API 参数:
ALTER TABLE table_name MODIFY COLUMN column_name API_KEY='key';
ALTER TABLE table_name MODIFY COLUMN column_name API_URL='url';
ALTER TABLE table_name MODIFY COLUMN column_name API_TIMEOUT='seconds';
- Example
ALTER TABLE rt MODIFY COLUMN vector API_KEY='new-key';
ALTER TABLE rt MODIFY COLUMN vector API_URL='https://custom-api.example.com/v1/embeddings';
ALTER TABLE rt MODIFY COLUMN vector API_TIMEOUT='30';注意事项:
API_KEY:在 ALTER 操作期间通过实际 API 请求验证新 API 密钥。API_URL:设置为空字符串 ('') 以恢复到默认提供方端点。API_TIMEOUT:设置为'0'以使用默认超时时间(10 秒)。必须是非负整数。
要更改分布式表中的本地或远程节点列表,请遵循与创建表时相同的语法。只需将命令中的CREATE替换为ALTER,并移除type='distributed':
ALTER TABLE `distr_table_name` [[local='local_table_name'], [agent='host:port:remote_table'] ... ]
注意:在线更改分布式表的模式需要Manticore Buddy。如果不起作用,请确保Buddy已安装。
- Example
ALTER TABLE local_dist local='index1' local='index2' agent='127.0.0.1:9312:remote_table';