Index StructArray Fields
在运行向量搜索或加速标量过滤之前,请先为 StructArray 子字段创建 Index。对于 StructArray 字段,Index 目标是子字段路径,例如 chunks[emb_list_vector]、chunks[emb] 或 chunks[section]。
本页使用 Create a StructArray Field 中的 tech_articles Collection。chunks StructArray 字段包含用于过滤的标量子字段和用于搜索的向量子字段。
Before you begin
确保 Collection Schema 已包含 chunks StructArray 字段,并且已插入数据。
| 子字段路径 | 类型 | 索引用途 |
|---|---|---|
chunks[emb_list_vector] | FLOAT_VECTOR | 使用 MAX_SIM* metrics 进行 EmbeddingList search。 |
chunks[emb] | FLOAT_VECTOR | 使用常规向量 metrics 进行元素级 search。 |
chunks[section] | VARCHAR | 类别过滤。 |
chunks[quality_score] | FLOAT | 数值过滤和范围类谓词。 |
chunks[has_code] | BOOL | 布尔过滤。 |
一个 vector field 或 vector subfield 只能接受一个 index。如果你同时需要 EmbeddingList search 和元素级 search,请创建两个独立的 vector subfield,并分别为它们创建 index。在本页中,chunks[emb_list_vector] 用于 EmbeddingList search 的 index,chunks[emb] 用于元素级 search 的 index。
选择 Index
使用搜索模式选择向量 metric family。
| 搜索或过滤目标 | 目标路径 | 选择内容 |
|---|---|---|
| EmbeddingList 搜索 | chunks[emb_list_vector] | MAX_SIM* metric family。 |
| Element-level vector search(元素级向量搜索) | chunks[emb] | 常规 vector metric family,例如 COSINE、IP 或 L2。 |
| 按字符串或类别过滤 | chunks[section] | 目标支持的 scalar index。 |
| 按数值范围过滤 | chunks[quality_score]、chunks[page] | 目标支持的 scalar index。 |
| 按布尔值过滤 | chunks[has_code] | 目标支持的 scalar index。 |
EmbeddingList 搜索会将 StructArray 向量子字段中的向量视为 embedding list,并返回 Entity 级结果。Element-level search 会独立搜索每个 Struct 元素,并可返回匹配元素的 offset。
创建 vector indexes
以下示例创建两个 vector index。第一个 index 使用 MAX_SIM* metric,用于 EmbeddingList search。第二个 index 使用常规 vector metric,用于 element-level search。
from pymilvus import MilvusClient
client = MilvusClient(
uri="http://localhost:19530",
token="root:Milvus",
)
index_params = client.prepare_index_params()
# Index for EmbeddingList search.
index_params.add_index(
field_name="chunks[emb_list_vector]",
index_name="chunks_emb_list_max_sim",
index_type="HNSW",
metric_type="MAX_SIM_COSINE",
params={
"M": 16,
"efConstruction": 200,
},
)
# Index for element-level search.
index_params.add_index(
field_name="chunks[emb]",
index_name="chunks_emb_cosine",
index_type="HNSW",
metric_type="COSINE",
params={
"M": 16,
"efConstruction": 200,
},
)
client.create_index(
collection_name="tech_articles",
index_params=index_params,
)
警告
不要在同一个 vector subfield 上同时创建 MAX_SIM* index 和常规 vector-metric index。如果需要同时使用这两种 search mode,请将 vectors 写入两个单独的 vector subfields,并在每个 subfield 上分别创建一个 index。
Create scalar indexes
当你在 Filter 中使用 StructArray 标量子字段时,为这些子字段创建 scalar indexes。使用相同的 structArray[subfield] 路径语法。
index_params = client.prepare_index_params()
index_params.add_index(
field_name="chunks[section]",
index_name="chunks_section_inverted",
index_type="INVERTED",
)
index_params.add_index(
field_name="chunks[has_code]",
index_name="chunks_has_code_inverted",
index_type="INVERTED",
)
index_params.add_index(
field_name="chunks[quality_score]",
index_name="chunks_quality_score_sort",
index_type="STL_SORT",
)
index_params.add_index(
field_name="chunks[page]",
index_name="chunks_page_sort",
index_type="STL_SORT",
)
client.create_index(
collection_name="tech_articles",
index_params=index_params,
)
scalar indexes 是可选的,但当 StructArray 标量子字段频繁出现在 Filter 中时会很有用,例如 element_filter(chunks, $[quality_score] > 0.9) 或 MATCH_ANY(chunks, $[section] == "index")。
Index metric compatibility
使用以下表格为 StructArray vector 子字段选择 index type 和 metric type。先从目标出发,然后根据 search mode 选择 metric family。
从以下兼容性表格中选择 Milvus index type 和 metric type。
EmbeddingList search
EmbeddingList search 使用 MAX_SIM* metric。它会将 StructArray 向量子字段中的 vector 视为一个 embedding list,并返回 entity 级别的结果。
| Vector subfield data type | Index type | Metric type |
|---|---|---|
FLOAT_VECTOR, FLOAT16_VECTOR, BFLOAT16_VECTOR | IVF_FLAT, IVF_FLAT_CC, HNSW, HNSW_SQ, HNSW_PQ, HNSW_PRQ, DISKANN | MAX_SIM, MAX_SIM_COSINE, MAX_SIM_IP, MAX_SIM_L2 |
INT8_VECTOR | HNSW, HNSW_SQ, HNSW_PQ, HNSW_PRQ | MAX_SIM, MAX_SIM_COSINE, MAX_SIM_IP, MAX_SIM_L2 |
BINARY_VECTOR | HNSW | MAX_SIM_HAMMING, MAX_SIM_JACCARD |
Element-level search
Element-level search 使用常规向量 Metric。它会独立搜索每个 Struct 元素,并可返回匹配元素的 offset。
| Vector subfield 数据类型 | Index 类型 | Metric 类型 |
|---|---|---|
FLOAT_VECTOR, FLOAT16_VECTOR, BFLOAT16_VECTOR | FLAT, IVF_FLAT, IVF_FLAT_CC, IVF_SQ8, IVF_SQ_CC, IVF_PQ, SCANN, IVF_RABITQ, IVF_RABITQ_FASTSCAN, HNSW, HNSW_SQ, HNSW_PQ, HNSW_PRQ, DISKANN | L2, IP, COSINE |
INT8_VECTOR | HNSW, HNSW_SQ, HNSW_PQ, HNSW_PRQ | L2, IP, COSINE |
BINARY_VECTOR | HNSW | HAMMING, JACCARD |
BINARY_VECTOR | BIN_FLAT | HAMMING, JACCARD, SUBSTRUCTURE, SUPERSTRUCTURE, MHJACCARD |
BINARY_VECTOR | BIN_IVF_FLAT | HAMMING, JACCARD |
有关特定版本的支持情况和其他限制,请参阅 StructArray Limits。
验证 Index
创建 Index 后,可以 describe Collection 或列出 Index,以确认预期的 subfield path 已建立 Index。
indexes = client.list_indexes(
collection_name="tech_articles",
)
print(indexes)
如果你的 SDK 版本提供 index-description API,也可以 describe 指定 Index。
index = client.describe_index(
collection_name="tech_articles",
index_name="chunks_emb_cosine",
)
print(index)
Index rules
| 规则 | 说明 |
|---|---|
| 对 subfield index 使用路径语法。 | 为 chunks[emb] 创建 index,而不是 emb 或 chunks.emb。 |
| 一个 vector subfield 只接受一个 index。 | 如果需要不同的 metric family,请使用单独的 vector subfield。 |
对 EmbeddingList search 使用 MAX_SIM* metric。 | EmbeddingList 查询数据要求使用基于 MAX_SIM* metric 构建的 index。 |
| 对 element-level search 使用常规 vector metric。 | Element-level search 使用常规 vector 查询数据,以及 COSINE、IP 或 L2 等 metric。 |
| 为出现在 Filter 中的 scalar subfield 创建 index。 | 使用目标支持的 scalar index 类型。 |
| 注意 vector field 限制。 | vector field 和 vector subfield 的总数有限。添加大量 vector subfield 前,请参阅 StructArray Limits。 |
常见错误
-
在
chunks.emb而不是chunks[emb]上创建 Index。 -
只创建
MAX_SIM*Index,却尝试在同一个 subfield 上运行元素级搜索。 -
只创建常规 vector Index,却尝试在同一个 subfield 上运行 EmbeddingList 搜索。
-
将同一个 vector subfield 同时用于
MAX_SIM*和常规 vector metrics。 -
忘记为高频使用的 StructArray Filter 创建 scalar Index。
-
为 Struct schema 中不存在的 StructArray subfield 创建 Index。
后续步骤
-
如需执行 entity-level EmbeddingList search 或 element-level vector search,请阅读 Basic Vector Search with StructArray。
-
如需在搜索期间过滤 StructArray scalar subfield,请阅读 Filtered Search with StructArray。
-
如需查看 index 和 metric 限制,请阅读 StructArray Limits。